Compare commits

...

389 Commits

Author SHA1 Message Date
Greg Turnquist
fbec97fcd6 DATAMONGO-2535 - Remove Travis CI. 2020-05-04 15:09:47 -05:00
Mark Paluch
90a6f657e5 DATAMONGO-2337 - Add HTTPS entries into spring.schemas.
To resolve XSD files properly from the classpath, their HTTPS reference must be present in the spring.schemas to avoid internet interaction for resolving an XSD file.
2019-08-06 15:58:44 +02:00
Greg Turnquist
180f34f1e4 DATAMONGO-2280 - Force check for updates. 2019-08-05 11:08:03 -05:00
Mark Paluch
6ad5e3ad18 DATAMONGO-2303 - Updated changelog. 2019-08-05 15:57:34 +02:00
Mark Paluch
618c274e59 DATAMONGO-2302 - Updated changelog. 2019-08-05 11:34:31 +02:00
Mark Paluch
795e507b25 DATAMONGO-2272 - After release cleanups. 2019-08-05 10:57:37 +02:00
Mark Paluch
64cfaf6a4f DATAMONGO-2272 - Prepare next development iteration. 2019-08-05 10:57:37 +02:00
Mark Paluch
43224ccec7 DATAMONGO-2272 - Release version 1.10.23 (Ingalls SR23). 2019-08-05 10:37:40 +02:00
Mark Paluch
54ef3305ae DATAMONGO-2272 - Prepare 1.10.23 (Ingalls SR23). 2019-08-05 10:37:16 +02:00
Mark Paluch
fa2dbf13a9 DATAMONGO-2272 - Updated changelog. 2019-08-05 10:37:13 +02:00
Mark Paluch
7c215a9ebf DATAMONGO-2318 - Fix typo. 2019-07-10 09:46:26 +02:00
Mark Paluch
c9287a2465 DATAMONGO-2280 - Cleanup release profile.
Reuse inherited configuration from parent pom.
2019-07-09 11:02:19 +02:00
Mark Paluch
5f070ee9de DATAMONGO-2318 - Revise readme for a consistent structure. 2019-07-09 11:02:19 +02:00
Greg Turnquist
0b963fd9c6 DATAMONGO-2280 - Polishing. 2019-07-03 17:13:10 -05:00
Greg Turnquist
29849dcd13 DATAMONGO-2280 - Use parent 'artifactory' profile for snapshot releases. 2019-07-03 17:12:44 -05:00
Greg Turnquist
27dc8bcade DATAMONGO-2280 - Only test main branch for upstream triggers. 2019-06-28 19:32:12 -05:00
Greg Turnquist
fe4597f0e6 DATAMONGO-2280 - Set user.name and user.home for CI jobs. 2019-06-25 13:36:22 -05:00
Christoph Strobl
902ea24ded DATAMONGO-2256 - Updated changelog. 2019-06-14 15:17:55 +02:00
Christoph Strobl
2e12f3a22e DATAMONGO-2271 - Updated changelog. 2019-06-14 13:27:17 +02:00
Greg Turnquist
ebc22c8d32 DATAMONGO-2280 - Add maven wrapper. 2019-06-11 15:16:10 -05:00
Greg Turnquist
9e01c4aad5 DATAMONGO-2280 - Introduce Jenkins. 2019-06-11 15:12:02 -05:00
Mark Paluch
bd2b2653c3 DATAMONGO-2270 - After release cleanups. 2019-05-13 18:14:55 +02:00
Mark Paluch
fb3655329b DATAMONGO-2270 - Prepare next development iteration. 2019-05-13 18:14:51 +02:00
Mark Paluch
a5cefddbcc DATAMONGO-2270 - Release version 1.10.22 (Ingalls SR22). 2019-05-13 17:25:16 +02:00
Mark Paluch
fe3f358480 DATAMONGO-2270 - Prepare 1.10.22 (Ingalls SR22). 2019-05-13 17:24:29 +02:00
Mark Paluch
d7a63ac882 DATAMONGO-2270 - Updated changelog. 2019-05-13 17:24:23 +02:00
Mark Paluch
526037e71b DATAMONGO-2269 - Updated changelog. 2019-05-13 14:59:29 +02:00
Mark Paluch
2ba6f48335 DATAMONGO-2260 - Updated changelog. 2019-05-13 12:37:43 +02:00
Oliver Drotbohm
ed22672b5c DATAMONGO-2244 - After release cleanups. 2019-05-10 14:15:20 +02:00
Oliver Drotbohm
7c94718c9b DATAMONGO-2244 - Prepare next development iteration. 2019-05-10 14:15:18 +02:00
Oliver Drotbohm
d56d84924a DATAMONGO-2244 - Release version 1.10.21 (Ingalls SR21). 2019-05-10 13:30:51 +02:00
Oliver Drotbohm
034d3f4d43 DATAMONGO-2244 - Prepare 1.10.21 (Ingalls SR21). 2019-05-10 13:30:15 +02:00
Oliver Drotbohm
c9a6a04fc3 DATAMONGO-2244 - Updated changelog. 2019-05-10 13:30:09 +02:00
Oliver Drotbohm
fb8fd05cf0 DATAMONGO-2246 - Updated changelog. 2019-05-10 12:57:23 +02:00
Christoph Strobl
8c62077d08 DATAMONGO-2222 - Updated changelog. 2019-04-11 12:28:55 +02:00
Oliver Drotbohm
23967107f2 DATAMONGO-2204 - Updated changelog. 2019-04-01 20:56:31 +02:00
Oliver Drotbohm
704a9658a7 DATAMONGO-2186 - Updated changelog. 2019-04-01 19:37:04 +02:00
Oliver Drotbohm
a394d1ea8e DATAMONGO-2243 - After release cleanups. 2019-04-01 18:16:19 +02:00
Oliver Drotbohm
b35e2e8eb8 DATAMONGO-2243 - Prepare next development iteration. 2019-04-01 18:16:18 +02:00
Oliver Drotbohm
26cda42892 DATAMONGO-2243 - Release version 1.10.20 (Ingalls SR20). 2019-04-01 17:40:06 +02:00
Oliver Drotbohm
145fc27bd9 DATAMONGO-2243 - Prepare 1.10.20 (Ingalls SR20). 2019-04-01 17:39:38 +02:00
Oliver Drotbohm
57b541ac86 DATAMONGO-2243 - Updated changelog. 2019-04-01 17:39:33 +02:00
Oliver Drotbohm
a21a539c83 DATAMONGO-2185 - After release cleanups. 2019-04-01 13:31:15 +02:00
Oliver Drotbohm
89fef9306f DATAMONGO-2185 - Prepare next development iteration. 2019-04-01 13:31:14 +02:00
Oliver Drotbohm
b2b67270d1 DATAMONGO-2185 - Release version 1.10.19 (Ingalls SR19). 2019-04-01 13:08:18 +02:00
Oliver Drotbohm
4d72b0b78f DATAMONGO-2185 - Prepare 1.10.19 (Ingalls SR19). 2019-04-01 13:07:51 +02:00
Oliver Drotbohm
cd510d97bd DATAMONGO-2185 - Updated changelog. 2019-04-01 13:07:47 +02:00
Spring Operator
bbcaf361c6 DATAMONGO-2231 - URL Cleanup.
This commit updates URLs to prefer the https protocol. Redirects are not followed to avoid accidentally expanding intentionally shortened URLs (i.e. if using a URL shortener).

# Fixed URLs

## Fixed Success
These URLs were switched to an https URL with a 2xx status. While the status was successful, your review is still recommended.

* [ ] http://www.apache.org/licenses/ with 1 occurrences migrated to:
  https://www.apache.org/licenses/ ([https](https://www.apache.org/licenses/) result 200).
* [ ] http://www.apache.org/licenses/LICENSE-2.0 with 587 occurrences migrated to:
  https://www.apache.org/licenses/LICENSE-2.0 ([https](https://www.apache.org/licenses/LICENSE-2.0) result 200).

Original Pull Request: #696
2019-03-22 09:39:13 +01:00
Spring Operator
4cf922a05b DATAMONGO-2231 - URL Cleanup.
This commit updates URLs to prefer the https protocol. Redirects are not followed to avoid accidentally expanding intentionally shortened URLs (i.e. if using a URL shortener).

# Fixed URLs

## Fixed Success
These URLs were switched to an https URL with a 2xx status. While the status was successful, your review is still recommended.

* http://maven.apache.org/xsd/maven-4.0.0.xsd with 3 occurrences migrated to:
  https://maven.apache.org/xsd/maven-4.0.0.xsd ([https](https://maven.apache.org/xsd/maven-4.0.0.xsd) result 200).
* http://www.gopivotal.com (302) with 6 occurrences migrated to:
  https://pivotal.io ([https](https://www.gopivotal.com) result 200).
* http://maven.apache.org/maven-v4_0_0.xsd with 3 occurrences migrated to:
  https://maven.apache.org/maven-v4_0_0.xsd ([https](https://maven.apache.org/maven-v4_0_0.xsd) result 301).
* http://projects.spring.io/spring-data-mongodb with 1 occurrences migrated to:
  https://projects.spring.io/spring-data-mongodb ([https](https://projects.spring.io/spring-data-mongodb) result 301).

# Ignored
These URLs were intentionally ignored.

* http://maven.apache.org/POM/4.0.0 with 12 occurrences
* http://www.w3.org/2001/XMLSchema-instance with 6 occurrences

Original Pull Request: #662
2019-03-19 12:52:52 +01:00
Christoph Strobl
da07d9e3f8 DATAMONGO-2164 - Updated changelog. 2019-03-07 10:30:12 +01:00
Mark Paluch
e0b0763349 DATAMONGO-2187 - Updated changelog. 2019-02-13 11:47:55 +01:00
Mark Paluch
00ca50cf17 DATAMONGO-2145 - Updated changelog. 2019-01-10 14:15:40 +01:00
Mark Paluch
3a461d2bc6 DATAMONGO-2144 - Updated changelog. 2019-01-10 12:26:38 +01:00
Mark Paluch
df3f91fff4 DATAMONGO-2143 - After release cleanups. 2019-01-10 10:46:20 +01:00
Mark Paluch
5d75c2a921 DATAMONGO-2143 - Prepare next development iteration. 2019-01-10 10:46:19 +01:00
Mark Paluch
d723784925 DATAMONGO-2143 - Release version 1.10.18 (Ingalls SR18). 2019-01-10 09:52:56 +01:00
Mark Paluch
a2426ec98d DATAMONGO-2143 - Prepare 1.10.18 (Ingalls SR18). 2019-01-10 09:52:13 +01:00
Mark Paluch
568f6bb1e0 DATAMONGO-2143 - Updated changelog. 2019-01-10 09:52:09 +01:00
Mark Paluch
c2f94cb840 DATAMONGO-2175 - Update copyright years to 2019. 2019-01-02 14:13:33 +01:00
Christoph Strobl
14981872e6 DATAMONGO-2160 - Updated changelog. 2018-12-11 11:43:16 +01:00
Christoph Strobl
624ec3ce55 DATAMONGO-2149 - Fix $slice in fields projection when pointing to array of DBRefs.
We now no longer try to convert the actual slice parameters into a DBRef.

Original pull request: #623.
2018-11-30 15:19:07 +01:00
Mark Paluch
db9d282313 DATAMONGO-2121 - Updated changelog. 2018-11-27 14:54:04 +01:00
Mark Paluch
10972bfda1 DATAMONGO-2109 - Updated changelog. 2018-11-27 12:36:49 +01:00
Mark Paluch
28454cb554 DATAMONGO-2110 - After release cleanups. 2018-11-27 11:10:58 +01:00
Mark Paluch
f17c4923e6 DATAMONGO-2110 - Prepare next development iteration. 2018-11-27 11:10:56 +01:00
Mark Paluch
4414771aaa DATAMONGO-2110 - Release version 1.10.17 (Ingalls SR17). 2018-11-27 10:15:45 +01:00
Mark Paluch
9acc558ae9 DATAMONGO-2110 - Prepare 1.10.17 (Ingalls SR17). 2018-11-27 10:14:58 +01:00
Mark Paluch
2d946a2c9a DATAMONGO-2110 - Updated changelog. 2018-11-27 10:14:54 +01:00
Oliver Drotbohm
715a2d3da4 DATAMONGO-2135 - Polishing. 2018-11-15 15:54:22 +01:00
Oliver Drotbohm
01c1ec2e5b DATAMONGO-2135 - Default to intermediate List for properties typed to Collection.
We now defensively create a List rather than a LinkedHashSet (which Spring's CollectionFactory.createCollection(…) defaults to) to make sure we're not accidentally dropping values that are considered equal according to their Java class definition.
2018-11-15 15:54:18 +01:00
Mark Paluch
7596f37235 DATAMONGO-2107 - Updated changelog. 2018-10-29 14:30:31 +01:00
Mona Mohamadinia
da4ccaa975 DATAMONGO-2118 - Fix typo in repositories reference documentation.
Original pull request: #611.
2018-10-26 10:08:55 +02:00
Mark Paluch
aed9b4d0da DATAMONGO-2083 - After release cleanups. 2018-10-15 13:55:50 +02:00
Mark Paluch
54a0e34049 DATAMONGO-2083 - Prepare next development iteration. 2018-10-15 13:55:49 +02:00
Mark Paluch
6cb8055601 DATAMONGO-2083 - Release version 1.10.16 (Ingalls SR16). 2018-10-15 12:56:30 +02:00
Mark Paluch
34829fca84 DATAMONGO-2083 - Prepare 1.10.16 (Ingalls SR16). 2018-10-15 12:55:35 +02:00
Mark Paluch
94b2495145 DATAMONGO-2083 - Updated changelog. 2018-10-15 12:55:29 +02:00
Mark Paluch
f2301eaf5b DATAMONGO-2084 - Updated changelog. 2018-10-15 12:46:26 +02:00
Mark Paluch
e3e201edb9 DATAMONGO-2094 - Updated changelog. 2018-10-15 11:37:25 +02:00
Christoph Strobl
c738148b40 DATAMONGO-2096 - Fix target field name for GraphLookup aggregation operation.
We now make sure to use the target field name instead of the alias when processing GraphLookupOperation.

Original pull request: #613.
2018-10-05 15:17:42 +02:00
Mark Paluch
ec5268a862 DATAMONGO-2061 - Updated changelog. 2018-09-21 08:13:12 -04:00
Mark Paluch
9bc073501f DATAMONGO-2034 - Updated changelog. 2018-09-10 14:15:51 +02:00
Mark Paluch
3d00ef1076 DATAMONGO-2035 - After release cleanups. 2018-09-10 10:01:44 +02:00
Mark Paluch
a07ca615be DATAMONGO-2035 - Prepare next development iteration. 2018-09-10 10:01:43 +02:00
Mark Paluch
15501f0424 DATAMONGO-2035 - Release version 1.10.15 (Ingalls SR15). 2018-09-10 09:30:36 +02:00
Mark Paluch
8d0edcd389 DATAMONGO-2035 - Prepare 1.10.15 (Ingalls SR15). 2018-09-10 09:29:51 +02:00
Mark Paluch
02241870d7 DATAMONGO-2035 - Updated changelog. 2018-09-10 09:29:48 +02:00
Oliver Gierke
d76dd90325 DATAMONGO-2076 - Fixed attribute substitution in getting started section. 2018-08-30 09:32:19 +02:00
Oliver Gierke
cc8c3448a8 DATAMONGO-2033 - Updated changelog. 2018-08-20 11:07:54 +02:00
Mark Paluch
3981a8ac92 DATAMONGO-2055 - Polishing.
Move test to UpdateMapperUnitTests.

Original pull request: #600.
2018-08-15 15:59:27 +02:00
Christoph Strobl
b9d72060af DATAMONGO-2055 - Allow position modifier to be negative using push at position on Update.
Original pull request: #600.
2018-08-15 15:54:27 +02:00
Mark Paluch
c1647ed269 DATAMONGO-2050 - Polishing.
Tweak Javadoc.

Original pull request: #596.
2018-08-15 15:28:56 +02:00
Christoph Strobl
9faeb1afe0 DATAMONGO-2050 - Allow to specify the index to use for $geoNear aggregation operation.
Original pull request: #596.
2018-08-15 15:28:56 +02:00
Mark Paluch
bbc7a64956 DATAMONGO-2051 - Polishing.
Use method argument types to avoid false positives with different method signatures.

Original pull request: #597.
Related pull request: #598.
2018-08-14 16:37:07 +02:00
Christoph Strobl
5f32339175 DATAMONGO-2051 - Add support for SCRAM-SHA-256 authentication mechanism to MongoCredentialPropertyEditor.
Original pull request: #597.
Related pull request: #598.
2018-08-14 16:37:04 +02:00
Christoph Strobl
013f56d141 DATAMONGO-2049 - Add support for $ltrim, $rtrim, and $trim.
Original pull request: #594.
2018-08-14 10:55:43 +02:00
Mark Paluch
ff9217b33e DATAMONGO-2048 - Polishing.
Javadoc tweaks.

Original pull request: #595.
2018-08-13 16:11:18 +02:00
Christoph Strobl
a87476f474 DATAMONGO-2048 - Add support for MongoDB 4.0 $convert aggregation operator.
We now support the following type conversion aggregation operators:

* $convert
* $toBool
* $toDate
* $toDecimal
* $toDouble
* $toInt
* $toLong
* $toObjectId
* $toString

Original pull request: #595.
2018-08-13 16:11:18 +02:00
Mark Paluch
df40a4820e DATAMONGO-2057 - Skip MongoDbUtils integration tests when running against MongoDB 4.0.
MongoDB 4.0 digests passwords by default which does not work with the SCRAM-SHA-256 authentication method so we skip those tests when running against MongoDB 4.0.
2018-08-13 14:09:20 +02:00
Mark Paluch
ac0aed8449 DATAMONGO-2047 - Polishing.
Retain previous options when calling withTimezone(…)/onNull…(…). Add tests. Javadoc.

Original pull request: #593.
2018-08-13 13:38:40 +02:00
Christoph Strobl
488462d5b3 DATAMONGO-2047 - Update $dateToString and $dateFromString aggregation operators to match MongoDB 4.0 changes.
We added the format and onNull options to DateFromString and changed format to an optional parameter.

Original pull request: #593.
2018-08-13 13:38:37 +02:00
Mark Paluch
639fecc9ca DATAMONGO-2043 - Polishing.
Slightly tweak Javadoc.

Original pull request: #589.
2018-08-08 11:11:41 +02:00
Christoph Strobl
47f9e3c739 DATAMONGO-2043 - Omit type hint when mapping simple types.
Original pull request: #589.
2018-08-08 11:11:35 +02:00
Mark Paluch
25507b995f DATAMONGO-2006 - After release cleanups. 2018-07-27 11:09:41 +02:00
Mark Paluch
1e29687135 DATAMONGO-2006 - Prepare next development iteration. 2018-07-27 11:09:38 +02:00
Mark Paluch
d594ae1bd0 DATAMONGO-2006 - Release version 1.10.14 (Ingalls SR14). 2018-07-27 09:21:39 +02:00
Mark Paluch
441e7fbb39 DATAMONGO-2006 - Prepare 1.10.14 (Ingalls SR14). 2018-07-27 09:20:28 +02:00
Mark Paluch
b9389860ce DATAMONGO-2006 - Updated changelog. 2018-07-27 09:20:21 +02:00
Mark Paluch
58426e0314 DATAMONGO-2007 - Updated changelog. 2018-07-26 16:24:01 +02:00
Mark Paluch
209466a85e DATAMONGO-1982 - Updated changelog. 2018-07-26 14:03:19 +02:00
Oliver Gierke
7c18b7dc0f DATAMONGO-2011 - Port unit test to verify Ingalls is not affected.
Original pull request: #587.
2018-07-13 12:59:38 +02:00
Christoph Strobl
3ff0975ab9 DATAMONGO-2023 - Polishing.
Add tests verifying the behavior when using both typed and untyped aggregation.

Original Pull Request: #585
2018-07-09 20:04:16 +02:00
Mark Paluch
ee9d8768a2 DATAMONGO-2023 - Polishing.
Remove trailing whitespaces.

Original Pull Request: #585
2018-07-09 19:58:07 +02:00
Mark Paluch
b77658e188 DATAMONGO-2023 - Allow usage of $sample in aggregation pipelines.
We now allow usage of $sample as aggregation framework stage and are no longer in the way with Query by Example. Previously, we identified Example objects using the $sample keyword which prevented query mapping of aggregation pipelines that contained a sample stage.

We already fixed this issue via DATAMONGO-1325 for the 2.x line.

Original Pull Request: #585
2018-07-09 19:57:35 +02:00
Mark Paluch
0cb0cb700b DATAMONGO-2016 - Polishing.
Fail gracefully if query string parameter has no value. Reformat test.

Original pull request: #578.
2018-07-04 11:25:21 +02:00
Stephen Tyler Conrad
364920e644 DATAMONGO-2016 - Fix username/password extraction in MongoCredentialPropertyEditor.
MongoCredentialPropertyEditor inspects now the connection URI for the appropriate delimiter tokens. Previously, inspection used the char questionmark for username/password delimiter inspection.

Original pull request: #578.
2018-07-04 11:24:50 +02:00
Mark Paluch
0495dd89ce DATAMONGO-1969 - Updated changelog. 2018-06-13 21:39:51 +02:00
Mark Paluch
19ccdd473a DATAMONGO-1967 - After release cleanups. 2018-06-13 14:42:35 +02:00
Mark Paluch
8fecc92dd4 DATAMONGO-1967 - Prepare next development iteration. 2018-06-13 14:42:33 +02:00
Mark Paluch
7fbb6583a5 DATAMONGO-1967 - Release version 1.10.13 (Ingalls SR13). 2018-06-13 10:48:53 +02:00
Mark Paluch
46550f6830 DATAMONGO-1967 - Prepare 1.10.13 (Ingalls SR13). 2018-06-13 10:48:03 +02:00
Mark Paluch
f076f75866 DATAMONGO-1967 - Updated changelog. 2018-06-13 10:47:57 +02:00
Mark Paluch
d9bf13cc1e DATAMONGO-2003 - Polishing.
Remove superfluous throws declarations and trailing whitespaces.

Original pull request: #570.
2018-06-11 14:29:11 +02:00
Christoph Strobl
626dfa4f9a DATAMONGO-2003 - Fix derived query using regex pattern with options.
We now consider regex pattern options when using the pattern as a derived finder argument.

Original pull request: #570.
2018-06-11 14:29:11 +02:00
Oliver Gierke
26c12214d3 DATAMONGO-2002 - Fixed Criteria.equals(…) for usage with Pattern instances.
For Criteria instances that use regular expressions we now properly compare the two Pattern instances produced by also including the pattern flags in the comparison.
2018-06-07 19:12:56 +02:00
Mark Paluch
f82b791f72 DATAMONGO-1998 - Polishing.
Switch id field name check to equals or to match the last property path segment.

Original pull request: #567.
2018-06-06 11:41:46 +02:00
Christoph Strobl
3785a52676 DATAMONGO-1998 - Fix Querydsl id handling for nested property references using ObjectId hex String representation.
We now follow the conversion rules for id properties with a valid ObjectId representation when parsing Querydsl queries.

Original pull request: #567.
2018-06-06 11:37:36 +02:00
Mark Paluch
41897c7d46 DATAMONGO-1986 - Polishing.
Refactor duplicated code into AggregationUtil.

Original pull request: #564.
2018-06-06 10:36:50 +02:00
Christoph Strobl
f3397e95bc DATAMONGO-1986 - Always provide a typed AggregationOperationContext for TypedAggregation.
We now initialize a TypeBasedAggregationOperationContext for TypedAggregations if no context is provided. This makes sure that potential Criteria objects are run trough the QueryMapper.
In case the default context is used we now also make sure to at least run the aggregation pipeline through the QueryMapper to avoid passing on non MongoDB simple types to the driver.

Original pull request: #564.
2018-06-06 10:36:50 +02:00
Mark Paluch
5807c5d8bc DATAMONGO-1988 - Polishing.
Match exactly for either top-level properties of leaf-properties instead of accepting the property/field name suffix. Downgrade tests to use DBObject API.

Original pull request: #565.
2018-06-05 11:23:00 +02:00
Christoph Strobl
70783d5806 DATAMONGO-1988 - Fix query creation for id property references using ObjectId hex String representation.
We now follow the conversion rules for id properties with a valid ObjectId representation when creating queries. Prior to this change e.g. String values would have been turned into ObejctIds when saving a document, but not when querying the latter.

Original pull request: #565.
2018-06-05 11:15:27 +02:00
Christoph Strobl
02e3fa1486 DATAMONGO-1927 - Updated changelog. 2018-05-17 10:32:55 +02:00
Victor
f09c956ab2 DATAMONGO-1978 - Fix minor typo in Field.positionKey field name.
Original pull request: #558.
2018-05-15 12:29:44 +02:00
Mark Paluch
6d6201d327 DATAMONGO-1466 - Polishing.
Remove superfluous static keyword in inner enum declarations. Fix typos in method names.

Original pull request: #561.
2018-05-15 11:19:43 +02:00
Christoph Strobl
5217e7a7e0 DATAMONGO-1466 - Add embedded typeinformation-based reading GeoJSON converter.
Original pull request: #561.
2018-05-15 11:19:25 +02:00
Mark Paluch
f56bb16a12 DATAMONGO-1974 - Polishing.
Fix typos, links, and code fences.

Original pull request: #559.
2018-05-11 15:39:18 +02:00
Jay Bryant
0869fdb5b8 DATAMONGO-1974 - Full editing pass for Spring Data MongoDB.
Full editing pass of the Spring Data MongoDB reference guide. I also adjusted index.adoc to work with the changes I made to the build project, so that we get Epub and PDF as well as HTML.

Original pull request: #559.
2018-05-11 15:36:37 +02:00
Mark Paluch
59aa9f96cc DATAMONGO-1918 - Updated changelog. 2018-05-08 15:27:19 +02:00
Mark Paluch
944fabb87d DATAMONGO-1917 - After release cleanups. 2018-05-08 11:56:07 +02:00
Mark Paluch
3cf2cd2d59 DATAMONGO-1917 - Prepare next development iteration. 2018-05-08 11:56:06 +02:00
Mark Paluch
44a4e65a72 DATAMONGO-1917 - Release version 1.10.12 (Ingalls SR12). 2018-05-08 10:50:35 +02:00
Mark Paluch
e378b6f4a6 DATAMONGO-1917 - Prepare 1.10.12 (Ingalls SR12). 2018-05-08 10:49:48 +02:00
Mark Paluch
61667bde17 DATAMONGO-1917 - Updated changelog. 2018-05-08 10:49:41 +02:00
Mark Paluch
4148e38ca9 DATAMONGO-1869 - Updated changelog. 2018-04-13 15:11:27 +02:00
Mark Paluch
e8d3c9e932 DATAMONGO-1893 - Polishing.
Inherit fields from previous operation if at least one field is excluded. Extend FieldsExposingAggregationOperation to conditionally inherit fields.

Backport to Java 6 code.

Original pull request: #538.
2018-04-06 10:45:48 +02:00
Christoph Strobl
fdc8ad8580 DATAMONGO-1893 - Allow exclusion of other fields than _id in aggregation $project.
As of MongoDB 3.4 exclusion of fields other than _id is allowed so we removed the limitation in our code.

Original pull request: #538.
2018-04-06 10:45:48 +02:00
Mark Paluch
e7cc9231ed DATAMONGO-1888 - Updated changelog. 2018-04-04 17:12:53 +02:00
Mark Paluch
2d2953cbc5 DATAMONGO-1857 - After release cleanups. 2018-04-04 14:58:03 +02:00
Mark Paluch
4dab0369ed DATAMONGO-1857 - Prepare next development iteration. 2018-04-04 14:58:02 +02:00
Mark Paluch
8ad0dc87e3 DATAMONGO-1857 - Release version 1.10.11 (Ingalls SR11). 2018-04-04 14:21:29 +02:00
Mark Paluch
16ad3c614f DATAMONGO-1857 - Prepare 1.10.11 (Ingalls SR11). 2018-04-04 14:20:47 +02:00
Mark Paluch
2663428825 DATAMONGO-1857 - Updated changelog. 2018-04-04 14:20:42 +02:00
Mark Paluch
f5d5a813f3 DATAMONGO-1903 - Polishing.
Remove client side operating system check as operating system-dependant constraints depend on the server. Add check on whitespaces. Add author tags. Extend tests. Extract database name assertion in an own method.

Original pull request: #546.
2018-04-03 13:44:35 +02:00
George Moraitis
b69ddd43ac DATAMONGO-1903 - Align database name check in SimpleMongoDbFactory with MongoDB limitations.
We now test database names against the current (3.6) MongoDB specifications for database names.

Original pull request: #546.
2018-04-03 13:44:33 +02:00
Mark Paluch
9f3dca3be9 DATAMONGO-1834 - Polishing.
Increase visibility of Timezone factory methods. Add missing nullable annotation. Tweaked Javadoc. Add tests for Timezone using expressions/field references.

Original Pull Request: #539
2018-03-28 14:29:56 +02:00
Christoph Strobl
49e97b7f47 DATAMONGO-1834 - Polishing.
Remove DateFactory and split up tests.
Introduce dedicated Timezone abstraction and update existing factories to apply the timezone if appropriate. Update builders and align code style.

Original Pull Request: #539
2018-03-28 13:55:53 +02:00
Matt Morrissette
7775746d26 DATAMONGO-1834 - Add support for MongoDB 3.6 DateOperators $dateFromString, $dateFromParts and $dateToParts including timezones.
Original Pull Request: #539
2018-03-28 13:28:43 +02:00
Oliver Gierke
67bae7c813 DATAMONGO-1915 - Removed explicit declaration of Jackson library versions. 2018-03-27 19:35:33 +02:00
Felipe Zanardo Affonso
038ab7d8bc DATAMONGO-1909 - Fix typo on return statement.
Original pull request: #523.
2018-03-21 16:05:53 +01:00
Oliver Gierke
0ac6956807 DATAMONGO-1898 - Fixed broken test cases.
Switched from AssertJ back to Hamcrest for matching.
2018-03-14 10:30:15 +01:00
Oliver Gierke
b1ec25d9be DATAMONGO-1901 - Added project.root configuration to make JavaDoc generation work again.
Related ticket: https://github.com/spring-projects/spring-data-build/issues/527.
2018-03-14 09:44:39 +01:00
Oliver Gierke
0a609d1ac9 DATAMONGO-1898 - Added unit tests for the conversion handling of enums implementing interfaces.
Related tickets: DATACMNS-1278.
2018-03-12 11:08:00 +01:00
Oliver Gierke
e4103eacda DATAMONGO-1896 - SimpleMongoRepository.saveAll(…) now consistently uses aggregate collection for inserts.
We previously used MongoTemplate.insertAll(…) which determines the collection to insert the individual elements based on the type, which - in cases of entity inheritance - will use dedicated collections for sub-types of the aggregate root. Subsequent lookups of the entities will then fail, as those are executed against the collection the aggregate root is mapped to.

We now rather use ….insert(Collection, String) handing the collection of the aggregate root explicitly.
2018-03-09 00:09:38 +01:00
Mark Paluch
bf58e9536b DATAMONGO-1882 - Updated changelog. 2018-02-28 11:17:41 +01:00
Mark Paluch
5fe67339e1 DATAMONGO-1859 - Updated changelog. 2018-02-19 20:30:08 +01:00
Mark Paluch
32a2970e76 DATAMONGO-1870 - Polishing.
Extend copyright license years. Slightly reword documentation.

Original pull request: #531.
Related pull request: #532.
2018-02-15 10:54:11 +01:00
Christoph Strobl
e8c9ac7dd0 DATAMONGO-1870 - Consider skip/limit on MongoOperations.remove(Query, Class).
We now use _id lookup for remove operations that query with limit or skip parameters. This allows more fine grained control over documents removed.

Original pull request: #531.
Related pull request: #532.
2018-02-15 10:53:43 +01:00
Christoph Strobl
29b4a9dcc3 DATAMONGO-1860 - Retrieve result count via QuerydslMongoPredicateExecutor only for paging.
We now use AbstractMongodbQuery.fetch() instead of AbstractMongodbQuery.fetchResults() to execute MongoDB queries. fetchResults() executes a find(…) and a count(…) query. Retrieving the record count is an expensive operation in MongoDB and the count is not always required. For regular find(…) method, the count is ignored, for paging the count(…) is only required in certain result/request scenarios.

Original Pull Request: #529
2018-02-14 13:58:10 +01:00
Christoph Strobl
7275a10c1e DATAMONGO-1871 - Fix AggregationExpression aliasing.
We now make sure to allow a nested property alias by setting the target.

Original pull request: #533.
2018-02-14 11:04:36 +01:00
Christoph Strobl
61b5977ada DATAMONGO-1794 - Updated changelog. 2018-02-06 11:13:59 +01:00
Mark Paluch
9ff3888a21 DATAMONGO-1830 - Updated changelog. 2018-01-24 13:41:25 +01:00
Mark Paluch
72f461ae30 DATAMONGO-1858 - Fix line endings to LF. 2018-01-24 12:57:54 +01:00
Mark Paluch
2af322a823 DATAMONGO-1829 - After release cleanups. 2018-01-24 12:16:41 +01:00
Mark Paluch
3694761f92 DATAMONGO-1829 - Prepare next development iteration. 2018-01-24 12:16:41 +01:00
Mark Paluch
c3b0e81db2 DATAMONGO-1829 - Release version 1.10.10 (Ingalls SR10). 2018-01-24 12:16:41 +01:00
Mark Paluch
27e68de5aa DATAMONGO-1829 - Prepare 1.10.10 (Ingalls SR10). 2018-01-24 12:16:41 +01:00
Mark Paluch
04ace43046 DATAMONGO-1829 - Updated changelog. 2018-01-24 12:16:32 +01:00
Mark Paluch
65996f3ad8 DATAMONGO-1843 - Polishing.
Typo fixes.

Original pull request: #526.
2018-01-23 10:46:37 +01:00
Christoph Strobl
237eace8e4 DATAMONGO-1843 - Fix parameter shadowing in ArrayOperators reduce.
Original pull request: #526.
2018-01-23 10:42:32 +01:00
Mark Paluch
0b31621d35 DATAMONGO-1824 - Switch to TravisCI-provided MongoDB service.
Original pull request: #521.
2017-12-15 14:30:53 +01:00
Mark Paluch
3f009053fe DATAMONGO-1824 - Polishing.
Move method from AggregationCommandPreparer and AggregationResultPostProcessor to BatchAggregationLoader. Extract field names to constants. Tiny renames to variables. Add unit test for aggregation response without cursor use.

Original pull request: #521.
2017-12-15 14:30:50 +01:00
Christoph Strobl
a2d470cd23 DATAMONGO-1824 - Skip tests no longer applicable for MongoDB 3.6.
Original pull request: #521.
2017-12-15 14:26:34 +01:00
Christoph Strobl
9525cdedfc DATAMONGO-1824 - Fix aggregation execution for MongoDB 3.6.
We now send aggregation commands along a cursor batch size for compatibility with MongoDB 3.6 that no longer supports aggregations without cursor. We consume the whole cursor before returning and converting results and omit the 16MB aggregation result limit. For MongoDB versions not supporting aggregation cursors we return results directly.

Original pull request: #521.
2017-12-15 14:26:12 +01:00
Christoph Strobl
867fcf6df2 DATAMONGO-1831 - Fix array type conversion for empty source.
We now make sure that we convert empty sources to the corresponding target type. This prevents entity instantiation from failing due to incorrect argument types when invoking the constructor.

Original pull request: #520.
2017-12-02 12:10:43 -08:00
Mark Paluch
3ddac744ce DATAMONGO-1816 - Updated changelog. 2017-11-27 16:43:42 +01:00
Mark Paluch
e565d25084 DATAMONGO-1799 - After release cleanups. 2017-11-27 15:56:39 +01:00
Mark Paluch
27623fce01 DATAMONGO-1799 - Prepare next development iteration. 2017-11-27 15:56:37 +01:00
Mark Paluch
c9d471e5d5 DATAMONGO-1799 - Release version 1.10.9 (Ingalls SR9). 2017-11-27 15:17:06 +01:00
Mark Paluch
6641277aaa DATAMONGO-1799 - Prepare 1.10.9 (Ingalls SR9). 2017-11-27 15:16:09 +01:00
Mark Paluch
29eba6e427 DATAMONGO-1799 - Updated changelog. 2017-11-27 15:16:04 +01:00
Oliver Gierke
d10e4afefd DATAMONGO-1737 - BasicMongoPersistentEntity now correctly initializes comparator.
In BasicMongoPersistentEntity.verify() we now properly call the super method to make sure the comparators that honor the @Field's order value are initialized properly.
2017-11-17 14:59:03 +01:00
Oliver Gierke
14bb4b586f DATAMONGO-1793 - Updated changelog. 2017-10-27 16:36:48 +02:00
Christoph Strobl
d795836994 DATAMONGO-1809 - Fix positional parameter detection for PropertyPaths.
We now make sure to capture all digits for positional parameters.

Original pull request: #508.
2017-10-24 14:53:33 +02:00
Mark Paluch
d216fed8db DATAMONGO-1696 - Mention appropriate EnableMongoAuditing annotation in reference documentation. 2017-10-20 08:45:47 +02:00
Oliver Gierke
26b7267737 DATAMONGO-1775 - After release cleanups. 2017-10-11 19:00:15 +02:00
Oliver Gierke
69d749d028 DATAMONGO-1775 - Prepare next development iteration. 2017-10-11 19:00:10 +02:00
Oliver Gierke
946617f634 DATAMONGO-1775 - Release version 1.10.8 (Ingalls SR8). 2017-10-11 16:42:42 +02:00
Oliver Gierke
50bb03004f DATAMONGO-1775 - Prepare 1.10.8 (Ingalls SR8). 2017-10-11 16:41:08 +02:00
Oliver Gierke
2f68d8c85d DATAMONGO-1775 - Updated changelog. 2017-10-11 16:40:59 +02:00
Mark Paluch
ebfbc4e9d0 DATAMONGO-1776 - Updated changelog. 2017-10-02 11:41:32 +02:00
Christoph Strobl
b96707a0e2 DATAMONGO-1784 - Polishing.
Update JavaDoc, enforce nullability constraints and add tests.

Original Pull Request: #501
2017-09-20 13:20:11 +02:00
Sergey Shcherbakov
7523eedd8d DATAMONGO-1784 - Add expression support to GroupOperation#sum().
We now allow passing an AggregationExpression to GroupOperation.sum which allows construction of more complex expressions.

Original Pull Request: #501
2017-09-20 13:20:04 +02:00
Christoph Strobl
ae8df6b705 DATAMONGO-1782 - Polishing.
toCyclePath now returns an empty String when Path does not cycle.
Also split and add tests.

Original Pull Request: #500
2017-09-19 09:42:01 +02:00
Mark Paluch
72a0a5623a DATAMONGO-1782 - Detect type cycles using PersistentProperty paths.
We now rely on PersistentProperty paths to detect cycles between types. Cycles are detected when building up the path object and traversing PersistentProperty stops after the cycle was hit for the second time to generated indexes for at least one hierarchy level.

Previously, we used String-based property dot paths and compared whether paths to a particular property was already found by a substring search which caused false positives if a property was reachable via multiple paths.

Original Pull Request: #500
2017-09-19 09:41:25 +02:00
Oliver Gierke
5f8f858d89 DATAMONGO-1754 - Updated changelog. 2017-09-11 17:42:45 +02:00
Mark Paluch
8db4feeef0 DATAMONGO-1755 - After release cleanups. 2017-09-11 12:23:36 +02:00
Mark Paluch
b9a392168d DATAMONGO-1755 - Prepare next development iteration. 2017-09-11 12:23:35 +02:00
Mark Paluch
479dc3a0d6 DATAMONGO-1755 - Release version 1.10.7 (Ingalls SR7). 2017-09-11 11:45:05 +02:00
Mark Paluch
59ebbd3d35 DATAMONGO-1755 - Prepare 1.10.7 (Ingalls SR7). 2017-09-11 11:44:20 +02:00
Mark Paluch
38556f522f DATAMONGO-1755 - Updated changelog. 2017-09-11 11:44:15 +02:00
Christoph Strobl
166304849a DATAMONGO-1772 - Fix UpdateMapper type key rendering for abstract list elements contained in concrete typed ones.
Original pull request: #497.
2017-09-05 10:58:55 +02:00
Mark Paluch
f71b38b731 DATAMONGO-1768 - Polishing.
Extend javadocs. Make methods static/reorder methods where possible. Formatting.

Original pull request: #496.
2017-08-25 10:48:42 +02:00
Christoph Strobl
c4af78d81d DATAMONGO-1768 - Allow ignoring type restriction when issuing QBE.
We now allow to remove the type restriction inferred by the QBE mapping via an ignored path expression on the ExampleMatcher. This allows to create untyped QBE expressions returning all entities matching the query without limiting the result to types assignable to the probe itself.

Original pull request: #496.
2017-08-25 10:41:37 +02:00
Oliver Gierke
a281ec83b5 DATAMONGO-1765 - Polishing.
Formatting.
2017-08-07 17:35:11 +02:00
Oliver Gierke
407087b3a7 DATAMONGO-1765 - DefaultDbRefResolver now maps duplicate references correctly.
On bulk resolution of a DBRef array we now map the resulting documents back to their ids to make sure that reoccurring identifiers are mapped to the corresponding documents.
2017-08-07 17:35:11 +02:00
Mark Paluch
90411decce DATAMONGO-1756 - Polishing.
Add author tag.

Original pull request: #491.
2017-08-02 08:52:45 +02:00
Christoph Strobl
71135395c1 DATAMONGO-1756 - Fix nested field name resolution for arithmetic aggregation ops.
Original pull request: #491.
2017-08-02 08:52:45 +02:00
Oliver Gierke
9c43ece3a7 DATAMONGO-1750 - After release cleanups. 2017-07-27 00:21:39 +02:00
Oliver Gierke
283bfce2fe DATAMONGO-1750 - Prepare next development iteration. 2017-07-27 00:15:08 +02:00
Oliver Gierke
42cc6ff37f DATAMONGO-1750 - Release version 1.10.6 (Ingalls SR6). 2017-07-26 23:47:20 +02:00
Oliver Gierke
9ded78b13c DATAMONGO-1750 - Prepare 1.10.6 (Ingalls SR6). 2017-07-26 23:45:52 +02:00
Oliver Gierke
b0842a89fd DATAMONGO-1750 - Updated changelog. 2017-07-26 23:45:43 +02:00
Oliver Gierke
5a9eef7c96 DATAMONGO-1751 - Updated changelog. 2017-07-25 16:15:49 +02:00
Oliver Gierke
77425736e9 DATAMONGO-1717 - Updated changelog. 2017-07-25 10:04:03 +02:00
Oliver Gierke
6aa8f84428 DATAMONGO-1711 - After release cleanups. 2017-07-24 19:25:08 +02:00
Oliver Gierke
b83f2e9198 DATAMONGO-1711 - Prepare next development iteration. 2017-07-24 19:25:06 +02:00
Oliver Gierke
2171c814e8 DATAMONGO-1711 - Release version 1.10.5 (Ingalls SR5). 2017-07-24 18:44:18 +02:00
Oliver Gierke
d0e398a39c DATAMONGO-1711 - Prepare 1.10.5 (Ingalls SR5). 2017-07-24 18:43:23 +02:00
Oliver Gierke
428c60dee0 DATAMONGO-1711 - Updated changelog. 2017-07-24 18:43:16 +02:00
Oliver Gierke
80393b2dc2 DATAMONGO-1720 - Make sure benchmark module is not included by default.
The benchmarks module does not produce a JAR by default which let's our Maven Central deployment fail as a module has to produce one according to their rules. We're now only including the benchmark module when the benchmarks profile is active.
2017-07-24 18:39:38 +02:00
Oliver Gierke
c15a542863 DATAMONGO-1744 - Improved setup of default MongoMappingContext instances created.
We now make sure that the SimpleTypeHolder produced by MongoCustomConversions is used to set up default MongoMappingContext instances in (Reactive)MongoTemplate and unit tests.
2017-07-19 15:21:15 +02:00
Mark Paluch
92c6db13dc DATAMONGO-1703 - Polishing.
Use lombok's Value for ObjectPathItem. Make methods accessible in DefaultDbRefResolver before calling. Use class.cast to avoid warnings. Update Javadoc.

Original pull request: #478.
2017-07-14 11:47:59 +02:00
Christoph Strobl
1681bcd15b DATAMONGO-1703 - Convert resolved DBRef's from source that do not match the requested property type.
We now check if already resolved DBRef's are assignable to the target property type. If not, we perform conversion again to prevent ClassCastException when trying to assign non matching types.

Remove non applicable public modifiers in ObjectPath.

Original pull request: #478.
2017-07-14 11:47:59 +02:00
Mark Paluch
1f2d0da5ed DATAMONGO-1720 - Polishing.
Enhance benchmark statistics with Git/working tree details. Specify byte encoding for JSON to byte encoder.
Add status code check to HttpResultsWriter to verify that the results were accepted. Convert spaces to tabs in pom.xml.

Original pull request: #483.
2017-07-13 15:17:13 +02:00
Christoph Strobl
8009bd2846 DATAMONGO-1720 - Add JMH based benchmarks for MappingMongoConverter.
Run the benchmark via the maven profile "benchmarks":

    mvn -P benchmarks clean test

Or run them customized:

    mvn -P benchmarks -DwarmupIterations=2 -DmeasurementIterations=5 -Dforks=1 clean test

Original pull request: #483.
2017-07-13 15:17:09 +02:00
Oliver Gierke
cbd9807f16 DATAMONGO-1725 - Prevent NullPointerException in CloseableIterableCursorAdapter.close(). 2017-07-05 13:15:45 +02:00
Oliver Gierke
f672b17dfc DATAMONGO-1729 - Open projections don't get field restrictions applied.
We now only apply a field restriction if the projection used for a query is closed.
2017-07-03 22:17:38 +02:00
Oliver Gierke
2a018b04ec DATAMONGO-1723 - ConfigurationExtensionUnitTests now need to provide a BeanDefinitionRegistry. 2017-06-26 16:53:39 +02:00
Mark Paluch
8e748ab1c2 DATAMONGO-1678 - Polishing.
Use Lombok's Value annotation for immutable value objects. Use IllegalArgumentException for NonNull validation exceptions. Trim whitespaces, formatting.

Original pull request: #472.
2017-06-26 13:28:28 +02:00
Christoph Strobl
49f9307884 DATAMONGO-1678 - Run bulk update / remove documents through type mappers.
We now make sure to run any query / update object through the Query- / UpdateMapper. This ensures @Field annotations and potential custom conversions get processed correctly for update / remove operations.

Original pull request: #472.
2017-06-26 13:13:54 +02:00
Christoph Strobl
ebd8491642 DATAMONGO-1697 - Update MongoOperations JavaDoc regarding mapping limitations.
We now explicitly mention mapping/support limitations for API variants like count(Query, String) not having domain type specific information that allows field specific mapping.
2017-06-19 10:31:20 +02:00
Christoph Strobl
f581677bf2 DATAMONGO-1718 - Polishing.
Add test and hand over Object.class as placeholder for required domain type.

Original Pull Request: #469
2017-06-16 13:31:37 +02:00
Borislav Rangelov
a2a172e559 DATAMONGO-1718 - Fix MongoTemplate::findAllAndRemove(Query,String) delegating to wrong overload.
Original Pull Request: #469 (by Borislav Rangelov).
2017-06-16 13:31:26 +02:00
Mark Paluch
61fd09bb43 DATAMONGO-1688 - Updated changelog. 2017-06-14 17:35:01 +02:00
Mark Paluch
4b11d415f1 DATAMONGO-1672 - After release cleanups. 2017-06-08 11:26:20 +02:00
Mark Paluch
beabbc0307 DATAMONGO-1672 - Prepare next development iteration. 2017-06-08 11:26:18 +02:00
Mark Paluch
ad55a8bab7 DATAMONGO-1672 - Release version 1.10.4 (Ingalls SR4). 2017-06-08 10:56:51 +02:00
Mark Paluch
79e0b44b5e DATAMONGO-1672 - Prepare 1.10.4 (Ingalls SR4). 2017-06-08 10:56:03 +02:00
Mark Paluch
b747e226d7 DATAMONGO-1672 - Updated changelog. 2017-06-08 10:55:58 +02:00
Mark Paluch
0bdd4a2eb4 DATAMONGO-1671 - Updated changelog. 2017-06-07 12:23:37 +02:00
Christoph Strobl
dda91f9d48 DATAMONGO-1699 - Upgrade travis-ci build to use MongoDB 3.4 server.
We now do it explicitly as there seems to be almost no movement getting the alias on the whitelist.
2017-05-24 13:17:27 +02:00
Mark Paluch
d32afee0e0 DATAMONGO-1664 - Updated changelog. 2017-05-09 11:36:18 +02:00
Mark Paluch
5e4cced3e6 DATAMONGO-1205 - Polishing.
Add author tag. Extend year range in copyright header.

Original pull request: #397.
2017-04-20 08:36:04 +02:00
Martin Macko
375d59f7a2 DATAMONGO-1205 - Log only CyclicPropertyReferenceException message.
We log CyclicPropertyReferenceException with its message only and removed the stack trace from the log. The stacktrace points to a verifier location and is not particularly useful in finding the offending code. This change creates consistency over how CyclicPropertyReferenceException is logged.

Original pull request: #397.
2017-04-20 08:36:04 +02:00
Oliver Gierke
0fe197d608 DATAMONGO-1670 - Updated changelog. 2017-04-19 21:04:23 +02:00
Oliver Gierke
5325e46aaa DATAMONGO-1669 - After release cleanups. 2017-04-19 20:01:14 +02:00
Oliver Gierke
1fe5793bd7 DATAMONGO-1669 - Prepare next development iteration. 2017-04-19 20:01:12 +02:00
Oliver Gierke
909a0bb2f2 DATAMONGO-1669 - Release version 1.10.3 (Ingalls SR3). 2017-04-19 19:32:38 +02:00
Oliver Gierke
c3983a4a32 DATAMONGO-1669 - Prepare 1.10.3 (Ingalls SR3). 2017-04-19 19:32:01 +02:00
Oliver Gierke
94cd8fd827 DATAMONGO-1669 - Updated changelog. 2017-04-19 19:31:54 +02:00
Oliver Gierke
34ca906b80 DATAMONGO-1634 - Updated changelog. 2017-04-19 13:04:10 +02:00
Oliver Gierke
0a9f7d0e30 DATAMONGO-1633 - After release cleanups. 2017-04-19 11:48:46 +02:00
Oliver Gierke
36af892679 DATAMONGO-1633 - Prepare next development iteration. 2017-04-19 11:48:42 +02:00
Oliver Gierke
12f3dce709 DATAMONGO-1633 - Release version 1.10.2 (Ingalls SR2). 2017-04-19 10:11:28 +02:00
Oliver Gierke
ae3b4be772 DATAMONGO-1633 - Prepare 1.10.2 (Ingalls SR2). 2017-04-19 10:10:47 +02:00
Oliver Gierke
4f813ae7a7 DATAMONGO-1633 - Updated changelog. 2017-04-19 10:10:39 +02:00
Mark Paluch
bd92f67e54 DATAMONGO-1666 - Consider collection type in bulk DBRef fetching.
We now consider the property's collection type after bulk-fetching DBRefs before returning the actual result value. The issue got only visible if bulk fetching is possible and constructor creation is used. Setting the property value on through an property accessor works fine because the property accessor checks all values for assignability and potentially converts values to their target type. That's different for constructor creation.

Original Pull Request: #457
2017-04-13 11:27:26 +02:00
Oliver Gierke
63968513d9 DATAMONGO-1535 - Updated changelog. 2017-04-10 13:44:19 +02:00
Michael J. Simons
2b0026931a DATAMONGO-1662 - Fix classname in reference docs about projections in aggregations.
Original pull request: #455.
2017-04-10 09:12:38 +02:00
Mark Paluch
0df5e6ba58 DATAMONGO-1645 - Polishing.
Clean up appender and log level after test run. Suppress log output during tests.

Original pull request: #450.
2017-03-21 10:52:35 +01:00
Christoph Strobl
2a0a880f57 DATAMONGO-1645 - Safely serialize JSON output for log message in LoggingEventListener.
We now make sure to safely serialize JSON output for mapped documents. This prevents the logger from rendering false exception messages to log appender.

Original pull request: #450.
2017-03-21 10:33:37 +01:00
Mark Paluch
d920cee5e7 DATAMONGO-1620 - Polishing.
Use Integer.MIN_VALUE as placeholder for unset values to allow setting zero (immediately) and -1 (indefinite wait) server selection timeouts. Fix test method name. Add JavaDoc.

Original pull request: #449.
2017-03-13 16:21:12 +01:00
Christoph Strobl
3af2d810bc DATAMONGO-1620 - Add server-selection-timeout to XML MongoClientOptions config.
We now allow server-selection-timeout attribute on MongoClientOptions XML configuration for a MongoDB 3.x client.

Original pull request: #449.
2017-03-13 16:21:12 +01:00
Mark Paluch
a4c754467e DATAMONGO-1421 - Polishing.
Remove trailing whitespaces. Construct exception message with String.format(…).

Original pull request: #448.
2017-03-08 08:47:58 +01:00
Christoph Strobl
0ab635d7ee DATAMONGO-1421 - Fix serialization in error message causing error itself.
We now make sure to safely serialize the criteria object used for creating the error message when raising an `InvalidMongoDbApiUsageException` in cases where `addCriteria` is used to add multiple entries for the same property.

Original pull request: #448.
2017-03-08 08:47:58 +01:00
Oliver Gierke
ef46edc941 DATAMONGO-1639 - Polishing.
Formatting in MongoTemplateUnitTests.
2017-03-06 16:24:44 +01:00
Oliver Gierke
93f81f7321 DATAMONGO-1639 - Make sure BeforeConvertEvent sees new version for updates.
The changes for DATAMONGO-1617 subtley changed the behavior for entity updates in terms of the version value they see for entities using optimistic locking. Previously the updates already saw the new version value, where after the fix for DATAMONGO-1617 it saw the old one. That caused BeforeConvertEvent listeners not being able to distinguish between an original insert and the first update anymore.

This change is now rolled back and we introduced a test case that encodes this expectation explicitly.
2017-03-06 16:24:44 +01:00
Oliver Gierke
f42c24a605 DATAMONGO-1597 - Updated changelog. 2017-03-02 16:57:50 +01:00
Oliver Gierke
1ac88e44a1 DATAMONGO-1598 - After release cleanups. 2017-03-02 10:21:53 +01:00
Oliver Gierke
324f656410 DATAMONGO-1598 - Prepare next development iteration. 2017-03-02 10:21:36 +01:00
Oliver Gierke
265ad423e5 DATAMONGO-1598 - Release version 1.10.1 (Ingalls SR1). 2017-03-02 09:41:27 +01:00
Oliver Gierke
0a4310760c DATAMONGO-1598 - Prepare 1.10.1 (Ingalls SR1). 2017-03-02 09:33:27 +01:00
Oliver Gierke
38ce0a24cc DATAMONGO-1598 - Updated changelog. 2017-03-02 09:32:50 +01:00
Mark Paluch
fb835e6a29 DATAMONGO-1605 - Polishing.
Remove additional quoting around JSON serialization because JSON serialization adds quotes to a string. Reformat code.
2017-03-01 15:59:09 +01:00
Christoph Strobl
c77025859b DATAMONGO-1605 - Retain type of SpEL expression result when used in @Query.
Fix issue where any result of a SpEL expression had been treated as quoted String within the resulting MongoDB query.
2017-03-01 15:59:09 +01:00
Mark Paluch
61cb23db5c DATAMONGO-1600 - Make GraphLookupOperationBuilder public.
Make GraphLookupOperationBuilder public so it can be used in types outside the aggregation package.

Original Pull Request: #437
2017-03-01 12:55:27 +01:00
Mark Paluch
6f138e641b DATAMONGO-1603 - Polishing.
Remove code that became unused. Reformat code. Extend years in copyright header.

Original pull request: #441.
2017-03-01 08:54:57 +01:00
Christoph Strobl
5925b5133c DATAMONGO-1603 - Fix Placeholder not replaced correctly in @Query.
Fix issues when placeholders are appended with other chars eg. '?0xyz' or have been reused multiple times within the query. Additional tests and fixes for complex quoted replacements eg. in regex query. Rely on placeholder quotation indication instead of binding one. Might be misleading when placeholder is used more than once.

Original pull request: #441.
2017-03-01 08:43:31 +01:00
Oliver Gierke
9d4f34a6ff DATAMONGO-1617 - Reinstantiate version property initialization before BeforeConvertEvent publication.
Related pull request: #443.
2017-02-28 20:05:47 +01:00
Oliver Gierke
85ff5a7254 DATAMONGO-1617 - Polishing.
Some cleanups in MongoTemplateTests. Removed manual ID assignment in general id handling test to make sure we use the id generation. Removed unneccessary code from domain type in favor of Lombok.

Original pull request: #443.
2017-02-28 18:07:28 +01:00
Laszlo Csontos
593c5366fa DATAMONGO-1617 - BeforeConvertEvent is now emitted before updatable idendifier assertion.
We now make sure the BeforeConvertEvent is published before we check for identifier types that can potentially be auto-generated. That allows the event listeners to populate identifiers. Previously the identifier check kicked in before that and thus caused the listener not being able to populate the property.

Original pull request: #443.
2017-02-28 18:07:28 +01:00
Christoph Strobl
9c06124943 DATAMONGO-1608 - Polishing.
Throw an IllegalArgumentException when trying to create a query using 'null' as an argument for queries resulting in a $regex query operator.

Original Pull Request: #439
2017-02-13 08:07:31 +01:00
Edward Prentice
e342008c4b DATAMONGO-1608 - Add guard against NPE in MongoQueryCreator when using IgnoreCase.
Original Pull Request: #439
2017-02-13 08:07:24 +01:00
Christoph Strobl
a4782ae9ec DATAMONGO-1607 - Polishing.
Move coordinate conversion to dedicated method. Additionally fix issue with assertions applied to late in the chain and added some tests.

Original Pull Request: #438
2017-02-10 14:10:13 +01:00
Thiago Diniz da Silveira
4cc52dc1e1 DATAMONGO-1607 - Fix ClassCastException in Circle, Point and Sphere when coordinates are not Double.
Original Pull Request: #438
2017-02-10 14:10:04 +01:00
Mark Paluch
e41e072217 DATAMONGO-1602 - Remove references to Assert single-arg methods.
Replace references to Assert single-arg methods with references to methods accepting the test object and message.

Related ticket: SPR-15196.
2017-02-01 11:23:39 +01:00
Oliver Gierke
d199a40664 DATAMONGO-1573 - Updated changelog. 2017-01-26 12:08:50 +01:00
Oliver Gierke
25d29a2332 DATAMONGO-1574 - After release cleanups. 2017-01-26 10:57:47 +01:00
Oliver Gierke
b19816490f DATAMONGO-1574 - Prepare next development iteration. 2017-01-26 10:57:44 +01:00
Oliver Gierke
d5fec0989c DATAMONGO-1574 - Release version 1.10 GA (Ingalls). 2017-01-26 10:27:10 +01:00
Oliver Gierke
52b52dba93 DATAMONGO-1574 - Prepare 1.10 GA (Ingalls). 2017-01-26 10:26:35 +01:00
Oliver Gierke
d046f30862 DATAMONGO-1574 - Updated changelog. 2017-01-26 10:26:33 +01:00
Christoph Strobl
7413a031c1 DATAMONGO-1517 - Polishing.
Remove ReflectiveSimpleTypes in favor of MongoSimpleTypes.
Add add integration test.
2017-01-25 16:57:20 +01:00
Mark Paluch
8e3d7f96c4 DATAMONGO-1517 - Add support for Decimal128 BSON type.
Support Decimal128 as Mongo simple type if present. Decimal128 is stored as NumberDecimal.

class Person {

  String id;
  Decimal128 decimal128;

  Person(String id, Decimal128 decimal128) {
    this.id = id;
    this.decimal128 = decimal128;
  }
}

mongoTemplate.save(new Person("foo", new Decimal128(new BigDecimal("123.456"))));

is represented as:

{ "_id" : "foo", "decimal128" : NumberDecimal("123.456") }
2017-01-25 16:57:20 +01:00
Mark Paluch
d2d162dee6 DATAMONGO-1596 - Fix typo in JavaDoc.
Use correct @RelatedDocument annotation in MongoDB cross store reference documentation.
2017-01-25 16:53:26 +01:00
Mark Paluch
b9aa410ac1 DATAMONGO-1575 - Polishing.
Extend year range in license headers. Use MongoDB JSON serializer for String escaping. Move unquoting/quote checking to inner QuotedString utility class. Reformat code.
2017-01-25 11:48:14 +01:00
Christoph Strobl
6f278ce838 DATAMONGO-1575 - Escape Strings correctly.
Use regex groups and parameter index values for replacement in string based queries.
2017-01-25 11:48:14 +01:00
Christoph Strobl
3ed72a922a DATAMONGO-1594 - Update "what’s new" section in reference documentation. 2017-01-23 08:16:02 +01:00
Oliver Gierke
98b3c1678f DATAMONGO-1592 - Adapt AuditingEventListenerUnitTests to changes in core auditing.
The core auditing implementation now skips the invocation of auditing in case the candidate aggregate doesn't need any auditing in the first place. We needed to adapt the sample class we use to actually carry the necessary auditing annotations.

Related ticket: DATACMNS-957.
2017-01-20 16:33:59 +01:00
Oliver Gierke
45818f26b3 DATAMONGO-1590 - Polishing.
Removed some compiler warnings. Hide newly introduced class in package scope and made use of Lombok annotations to avoid boilerplate code.

Original pull request: #436.
2017-01-18 19:41:11 +01:00
Christoph Strobl
822e29524d DATAMONGO-1590 - EntityInformation selected now correctly considers Persistable.
We now wrap the MappingMongoEntityInformation into one that delegates the methods implemented by Persistable to the actual entity in case it implements said interface.

Original pull request: #436.
2017-01-18 19:39:53 +01:00
Mark Paluch
3476c639c2 DATAMONGO-1588 - Polishing.
Remove unused fields. Fix typo in method name. Reformat inner class to align formatting.

Original pull request: #435.
2017-01-16 09:12:33 +01:00
Christoph Strobl
35fa922daa DATAMONGO-1588 - Fix derived finder not accepting subclass of parameter type.
We now allow using sub types as arguments for derived queries. This makes it possible to use eg. a GeoJsonPoint for querying while the declared property type in the domain object remains a regular (legacy) Point.

Original pull request: #435.
2017-01-16 09:12:33 +01:00
Mark Paluch
8f7ea3a2ed DATAMONGO-1589 - Update project documentation with the CLA tool integration. 2017-01-13 11:46:51 +01:00
Mark Paluch
7ab7212edc DATAMONGO-1587 - Polishing.
Convert @see http://… links to valid format using @see <a href=…>…</a>
2017-01-12 17:08:07 +01:00
Mark Paluch
27651ef0be DATAMONGO-1587 - Migrate ticket references in test code to Spring Framework style. 2017-01-12 16:17:39 +01:00
Mark Paluch
174f7f0886 DATAMONGO-1586 - Consider field name in TypeBasedAggregationOperationContext.getReferenceFor(…).
We now consider the provided field name (alias) in mapped fields with which it is exposed. The field name applies to the exposed field after property path resolution in TypeBasedAggregationOperationContext. Previously, the field reference used the property name which caused fields to be considered non-aliased, so aggregation projection operations dropped the alias and exposed the field with its leaf property name.

Original Pull Request: #434
2017-01-12 09:51:13 +01:00
Christoph Strobl
437bf89533 DATAMONGO-1585 - Polishing.
Update documentation for better readability in html and pdf format.

Original Pull Request: #433
2017-01-12 09:42:20 +01:00
Mark Paluch
c3e5fca73d DATAMONGO-1585 - Expose synthetic fields in $project aggregation stage.
Field projections now expose their fields as synthetic simple fields. Projection aggregation stage redefines the available field set available for later aggregation stages entirely so projected fields are considered synthetic. A simple synthetic field has no target field which causes later aggregation stages to not pick up the underlying target but the exposed field name when rendering aggregation operations to Mongo documents.

The change is motivated by a bug where previously an aggregation consisting of projection of an aliased field and sort caused the sort projection stage to render with the original field name instead of the aliased field. The sort did not apply any sorting since projection redefines the available field set entirely and the original field is no longer accessible.

Original Pull Request: #433
2017-01-12 09:41:26 +01:00
Christoph Strobl
8340c02d9a DATAMONGO-1576 - Update lifecycle event documentation.
Add note on lifecycle event handling for property types.
2017-01-11 13:10:48 +01:00
Mark Paluch
3c6db34870 DATAMONGO-1578 - Polishing.
Add ticket references to test methods. Extend license years in copyright header.

Original pull request: #398.
2017-01-02 11:39:24 +01:00
Martin Macko
9f3319928b DATAMONGO-1578 - Add missing @Test annotation to ProjectionOperationUnitTests.
Original pull request: #398.
2017-01-02 11:38:49 +01:00
Mark Paluch
97a03d824a DATAMONGO-1508 - Improve reference documentation.
Replace Spring Data Document with Spring Data MongoDB. Extend copyright year range. Replace static Spring version leftover with variable. Fix typos.
2017-01-02 11:18:53 +01:00
Lukasz Kryger
8149273df9 DATAMONGO-1577 - Fix wording repetition in MongoRepository JavaDoc.
Original pull request: #407.
2017-01-02 11:18:53 +01:00
Ken Dombeck
e838662536 DATAMONGO-1577 - Fix Reference and JavaDoc spelling issues.
Replaced invalid class name MongoMappingConverter with actual class name of MappingMongoConverter. Fix typos.

Original pull request: #425.
2017-01-02 11:18:49 +01:00
Mark Paluch
e784e58a0a DATAMONGO-1508 - Polishing.
Highlight attribute name. Replace tabs with spaces.

Original pull request: #399.
2017-01-02 10:43:49 +01:00
John Lilley
fda72d6eb2 DATAMONGO-1508 - Document authentication-dbname attribute in db-factory.
Original pull request: #399.
2017-01-02 10:43:39 +01:00
Oliver Gierke
a96752da80 DATAMONGO-1522 - Updated changelog. 2016-12-21 19:35:31 +01:00
Oliver Gierke
320a28740a DATAMONGO-1469 - After release cleanups. 2016-12-21 16:33:13 +01:00
Oliver Gierke
e55e748cfd DATAMONGO-1469 - Prepare next development iteration. 2016-12-21 16:33:10 +01:00
Oliver Gierke
737f7b4f30 DATAMONGO-1469 - Release version 1.10 RC1 (Ingalls). 2016-12-21 16:16:51 +01:00
Oliver Gierke
408c5d8684 DATAMONGO-1469 - Prepare 1.10 RC1 (Ingalls). 2016-12-21 16:15:47 +01:00
Oliver Gierke
982adf317e DATAMONGO-1469 - Updated changelog. 2016-12-21 16:15:39 +01:00
Oliver Gierke
7914e8a630 DATAMONGO-1467 - Polishing.
Original pull request: #431.
2016-12-19 19:44:47 +01:00
Christoph Strobl
dc4a30a7f8 DATAMONGO-1467 - Add support for MongoDB 3.2 partialFilterExpression for index creation.
We now support partial filter expression on indexes via Index.partial(…). This allows to create partial indexes that only index the documents in a collection that meet a specified filter expression. 

new Index().named("idx").on("k3y", ASC).partial(filter(where("age").gte(10)))

The filter expression can be set via a plain DBObject or a CriteriaDefinition and is mapped against the associated domain type.

Original pull request: #431.
2016-12-19 19:44:47 +01:00
Oliver Gierke
29e405b800 DATAMONGO-1565 - Polishing.
Formatting in ExpressionEvaluatingParameterBinder and StringBasedMongoQueryUnitTests. Turned Placeholder into value object.
2016-12-19 14:37:26 +01:00
Mark Paluch
1a105333aa DATAMONGO-1565 - Polishing.
Consider quoted/unquoted parameter use with the same parameter reference. Extend date range in license headers.
2016-12-19 14:37:26 +01:00
Christoph Strobl
14e326dc09 DATAMONGO-1565 - Ignore placeholder pattern in replacement values for annotated queries.
We now make sure to quote single and double ticks in the replacement values before actually appending them to the query. We also replace single ticks around parameters in the actual raw annotated query by double quotes to make sure they are treated as a single string parameter.
2016-12-19 14:36:44 +01:00
Mark Paluch
f026ab419d DATAMONGO-1564 - Polishing.
Fix JavaDoc references and minor a import formatting issue.

Original pull request: #429.
2016-12-16 14:11:18 +01:00
Christoph Strobl
75139042e0 DATAMONGO-1564 - Split up AggregationExpressions.
Refactored to multiple smaller Aggregation Operator classes reflecting the grouping (array operators, string operators,…) predefined by MongoDB.

Original pull request: #429.
2016-12-16 14:11:18 +01:00
Mark Paluch
6236384c1d DATAMONGO-1567 - Use newer Java 8 on Travis CI. 2016-12-16 10:47:02 +01:00
Mark Paluch
6993054d6a DATAMONGO-1533 - Polishing.
Enhance JavaDoc. Minor reformatting.

Original pull request: #428.
2016-12-16 09:25:00 +01:00
Christoph Strobl
35bfb92ace DATAMONGO-1533 - Add AggregationExpression derived from SpEL AST.
We added an AggregationExpression that renders a MongoDB Aggregation Framework expression from the AST of a SpEL expression. This allows usage with various stages (eg. $project, $group) throughout the aggregation support.

  // { $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')");

Original pull request: #428.
2016-12-16 09:02:15 +01:00
Oliver Gierke
89a02bb822 DATAMONGO-1566 - Adapt API in MongoRepositoryFactoryBean.
Related tickets: DATACMNS-891.
2016-12-15 14:57:26 +01:00
Christoph Strobl
c9c5fe62ca DATAMONGO-1552 - Polishing.
Updated doc, removed whitespaces, minor method wording changes.

Original Pull Request: #426
2016-12-14 12:05:26 +01:00
Mark Paluch
d250f88c38 DATAMONGO-1552 - Update Documentation.
Original Pull Request: #426
2016-12-14 11:09:46 +01:00
Mark Paluch
bcb63b2732 DATAMONGO-1552 - Add $facet aggregation stage.
Original Pull Request: #426
2016-12-14 11:09:01 +01:00
Mark Paluch
2c4377c9a6 DATAMONGO-1552 - Add $bucketAuto aggregation stage.
Original Pull Request: #426
2016-12-14 11:08:26 +01:00
Mark Paluch
e992d813fb DATAMONGO-1552 - Add $bucket aggregation stage.
Original Pull Request: #426
2016-12-14 11:07:40 +01:00
Mark Paluch
aa1e91c761 DATAMONGO-442 - Polishing.
Reformat code according to Spring Data style. Add test for authenticated use. Add JavaDoc to newly introduced methods. Allow configuration of an authentication database. Update reference documentation.

Original pull request: #419.
2016-12-13 16:50:37 +01:00
Ricardo Espirito Santo
9737464f9a DATAMONGO-442 - Support username/password authentication with MongoLog4jAppender.
Added optional username and password for authentication support on Log4jAppender.

Original pull request: #419.
2016-12-13 15:56:56 +01:00
Christoph Strobl
204a0515c4 DATAMONGO-1551 - Polishing.
Add startWith overload allowing to mix expressions, removed white spaces, updated doc.

Original Pull Request: #424
2016-12-13 15:15:55 +01:00
Mark Paluch
c6dae3c444 DATAMONGO-1551 - Add $graphLookup aggregation stage.
We now support the $graphLookup aggregation pipeline stage via Aggregation to perform recursive lookup adding the lookup result as array to documents entering $graphLookup.

TypedAggregation<Employee> agg = Aggregation.newAggregation(Employee.class,
		graphLookup("employee")
			.startWith("reportsTo")
			.connectFrom("reportsTo")
			.connectTo("name")
			.depthField("depth")
			.maxDepth(5)
			.as("reportingHierarchy"));

Original Pull Request: #424
2016-12-13 14:23:39 +01:00
Christoph Strobl
c1c7daf0ed DATAMONGO-1550 - Polishing $replaceRoot (aggregation stage).
Original Pull Request: #422.
2016-12-13 08:22:20 +01:00
Mark Paluch
14678ce7a9 DATAMONGO-1550 - Add $replaceRoot aggregation stage.
We now support the $replaceRoot stage in aggregation pipelines. $replaceRoot can reference either a field, an aggregation expression or it can be used to compose a replacement document.

newAggregation(
	replaceRoot().withDocument()
		.andValue("value").as("field")
		.and(MULTIPLY.of(field("total"), field("discounted")))
);

newAggregation(
	replaceRoot("item")));

Original Pull Request: #422
2016-12-13 08:22:20 +01:00
Christoph Strobl
4e56d9c575 DATAMONGO-1549 - Polishing $count (aggregation stage).
Original Pull Request: #422
2016-12-13 08:22:10 +01:00
Mark Paluch
cab35759db DATAMONGO-1549 - Add $count aggregation stage.
We now support the $count stage in aggregation pipelines.

newAggregation(
	match(where("hotelCode").is("0360")),
	count().as("documents"));

Original Pull Request: #422
2016-12-13 07:58:58 +01:00
Christoph Strobl
7b49b120e3 DATAMONGO-1558 - Upgrade MongoDB server version to, and add build profile for MongoDB 3.4.
Added MongoDB 3.4 profile to pom.xml and upgraded to MongoDB 3.4 on travis-ci.
2016-12-13 07:58:37 +01:00
Mark Paluch
dc57b66adf DATAMONGO-1548 - Polishing.
Enhance JavaDoc. Minor formatting. Fix typos.

Original pull request: #423.
2016-12-12 12:05:32 +01:00
Christoph Strobl
0449719a16 DATAMONGO-1548 - Add support for MongoDB 3.4 aggregation operators.
We now support the following MongoDB 3.4 aggregation operators:

$indexOfBytes, $indexOfCP, $split, $strLenBytes, $strLenCP, $substrCP, $indexOfArray, $range, $reverseArray, $reduce, $zip, $in, $isoDayOfWeek, $isoWeek, $isoWeekYear, $switch and $type.

Original pull request: #423.
2016-12-12 12:05:09 +01:00
Mark Paluch
3d8b6868c7 DATAMONGO-1538 - Polishing.
Use InheritingExposedFieldsAggregationOperationContext instead of anonymous context class for condition mapping. Drop aggregation input collections before tests. Minor reformatting.

Original pull request: #417.
2016-12-07 09:35:08 +01:00
Christoph Strobl
68db0d4cb0 DATAMONGO-1538 - Add support for $let to aggregation.
We now support $let in aggregation $project stage.

ExpressionVariable total = newExpressionVariable("total").forExpression(ADD.of(field("price"), field("tax")));
ExpressionVariable discounted = newExpressionVariable("discounted").forExpression(Cond.when("applyDiscount").then(0.9D).otherwise(1.0D));

newAggregation(Sales.class,
	project()
		.and(define(total, discounted)
			.andApply(MULTIPLY.of(field("total"), field("discounted"))))
		.as("finalTotal"));

Original pull request: #417.
2016-12-07 09:33:58 +01:00
Christoph Strobl
c9dfeea0c7 DATAMONGO-1542 - Polishing.
Added some static entry points for better readability.

Original Pull Request: #421
2016-12-06 10:13:32 +01:00
Mark Paluch
1a11877ae9 DATAMONGO-1542 - Refactor CondOperator and IfNullOperator to children of AggregationExpressions.
Renamed CondOperator to Cond and IfNullOperator to IfNull. Both conditional operations are now available from ConditionalOperators.when and ConditionalOperators.ifNull and accept AggregationExpressions for conditions and values.

Original Pull Request: #421
2016-12-06 09:19:28 +01:00
Christoph Strobl
ea4782c421 DATAMONGO-1520 - Add overload for aggregation $match accepting CriteriaDefinition.
We now also accept CriteriaDefinition next to Criteria for Aggregation.match. The existing match(Criteria) method remains to preserve binary compatibility.
2016-12-06 09:05:55 +01:00
Mark Paluch
a0ac3510a0 DATAMONGO-1540 - Polishing.
Reduce Map aggregation expression builder entrypoint. Fix JavaDoc.

Original pull request: #420.
2016-12-05 16:47:20 +01:00
Christoph Strobl
192399413d DATAMONGO-1540 - Add support for $map (aggregation).
We now support $map operator in aggregation.

Original pull request: #420.
2016-12-05 16:47:17 +01:00
Oliver Gierke
a0be890437 DATAMONGO-1547 - Register MongoRepositoryFactory in spring.factories.
This is required for the switch in support for multi-store detection.

Related ticket: DATACMNS-952.
2016-12-05 14:27:24 +01:00
Oliver Gierke
438dbc4b33 DATAMONGO-1546 - Register GeoJsonConfiguration via spring.factories.
Related tickets: DATACMNS-952.
2016-12-05 14:22:09 +01:00
Oliver Gierke
407affb458 DATAMONGO-1141 - Polishing.
Aligned assertion messages for consistency. Fixed imports in  UpdateMapperUnitTests.

Original pull request: #405.
2016-12-02 18:13:22 +01:00
Mark Paluch
c6a4e7166c DATAMONGO-1141 - Polishing.
Add property to field name mapping for Sort orders by moving Sort mapping to UpdateMapper. Fix typo. Add JavaDoc. Reformat code. Remove trailing whitespaces.

Original pull request: #405.
2016-12-02 18:13:18 +01:00
Pavel Vodrážka
7f39c42eb7 DATAMONGO-1141 - Add support for $push $sort in Update.
Sorting update modifier added. Supports sorting arrays by document fields and element values.

Original pull request: #405.
2016-12-02 18:13:02 +01:00
Oliver Gierke
40da4701de DATAMONGO-1454 - Polishing.
Formatting in test case.

Original pull request: #381.
2016-12-02 16:33:13 +01:00
Mark Paluch
3ae6aebebb DATAMONGO-1454 - Add support for exists projection in repository query methods.
We now support exists projections for query methods in query methods for derived and string queries.

public PersonRepository extends Repository<Person, String> {

  boolean existsByFirstname(String firstname);

  @ExistsQuery(value = "{ 'lastname' : ?0 }")
  boolean someExistQuery(String lastname);

  @Query(value = "{ 'lastname' : ?0 }", exists = true)
  boolean anotherExistQuery(String lastname);
}

Original pull request: #381.
2016-12-02 16:32:58 +01:00
Mark Paluch
bbfa0f7b83 DATAMONGO-1536 - Polishing.
Add JavaDoc. Change visibility of AbstractAggregationExpression.getMongoMethod() to protected.

Original pull request: #418.
2016-12-02 15:32:16 +01:00
Christoph Strobl
63d6234446 DATAMONGO-1536 - Add aggregation operators for array, arithmetic, date and set operations.
We now support the following aggregation framework operators:

- setEquals, setIntersection, setUnion, setDifference, setIsSubset, anyElementTrue, allElementsTrue
- stdDevPop, stdDevSamp
- abs, ceil, exp, floor, ln, log, log10, pow, sqrt, trunc
- arrayElementAt, concatArrays, isArray
- literal
- dayOfYear, dayOfMonth, dayOfWeek, year, month, week, hour, minute, second, millisecond, dateToString

Original pull request: #418.
2016-12-02 15:30:01 +01:00
Oliver Gierke
9ff86feb4f DATAMONGO-1539 - Polishing.
Renamed @Count and @Delete to @CountQuery and @DeleteQuery. Minor polishing in test cases and test repository methods. JavaDoc, formatting.

Original pull request: #416.
2016-12-02 11:55:14 +01:00
Fırat KÜÇÜK
8c838e8350 DATAMONGO-1539 - Introduce @CountQuery and @DeleteQuery.
Introducing dedicated annotations for manually defined count and delete queries to avoid misconfiguration and generally simplifying the declaration.

Original pull request: 416.
2016-12-02 11:55:07 +01:00
Oliver Gierke
a79930145d DATAMONGO-1525 - Improved creation of empty collections, esp. EnumSet.
We now use more type information to create a better empty collection in the first place. The previous algorithm always used an empty HashSet plus a subsequent conversion using the raw collection type. Especially the latter caused problems for EnumSets as the conversion into one requires the presence of component type information.

We now use Spring's collection factory and more available type information to create a proper collection in the first place and only rely on a subsequent conversion for arrays.
2016-12-01 20:10:41 +01:00
Christoph Strobl
9059a77712 DATAMONGO-1534 - Fix bulk operations missing to write type info.
We now correctly convert entities into their MongoDB representation including type information via _class property.

Original pull request: #415.
2016-11-28 09:06:13 +01:00
Christoph Strobl
a741400e9b DATAMONGO-1530 - Polishing.
Add missing transformations for ConstructorReference, OperatorNot, OpNE, OpEQ, OpGT, OpGE, OpLT, OpLE, OperatorPower, OpOr and OpAnd. This allows usage of logical operators &, || and ! as part of the expression, while ConstructorReference allows instantiating eg. arrays via an expression `new int[]{4,5,6}`. This can be useful eg. comparing arrays using $setEquals.

More complex aggregation operators like $filter can be created by defining the variable references as string inside the expression like filter(a, 'num', '$$num' > 10).
Commands like $let requires usage of InlineMap to pass in required arguments like eg. let({low:1, high:'$$low'}, gt('$$low', '$$high')).

Original Pull Request: #410
2016-11-25 15:45:14 +01:00
Sebastien Gerard
b786b8220a DATAMONGO-1530 - Add support for missing MongoDB 3.2 aggregation pipeline operators.
Original Pull Request: #410
2016-11-25 15:43:43 +01:00
Mark Paluch
710770e88d DATAMONGO-784 - Polishing.
Add JavaDoc for compareValue.

Original pull request: #414.
2016-11-24 13:56:27 +01:00
Christoph Strobl
e631e2d7c5 DATAMONGO-784 - Add support for comparison aggregation operators to group & project.
We now directly support comparison aggregation operators ($cmp, $eq, $gt, $gte, $lt, $lte and $ne) on both group and project stages.

Original pull request: #414.
2016-11-24 13:56:27 +01:00
Mark Paluch
3dc1e9355a DATAMONGO-1491 - Polishing.
Remove variable before returning value. Add generics for list creation.

Original pull request: #412.
2016-11-24 12:48:15 +01:00
Christoph Strobl
2985b4ca3d DATAMONGO-1491 - Add support for $filter (aggregation).
We new support $filter in aggregation pipeline.

Aggregation.newAggregation(Sales.class,
	Aggregation.project()
		.and(filter("items").as("item").by(GTE.of(field("item.price"), 100)))
		.as("items"))

Original pull request: #412.
2016-11-24 12:47:07 +01:00
Christoph Strobl
578441ee9f DATAMONGO-1327 - Polishing.
Just added overloads for stdDevSamp and stdDevPop taking AggregationExpression and updated the doc.
Also replaced String operation based MongoDB operation building by using operators directly.

Original Pull Request: #360
2016-11-23 15:39:01 +01:00
gustavodegeus
36838ffe31 DATAMONGO-1327 - Added support for $stdDevSamp and $stdDevPop to aggregation $group stage.
Original Pull Request: #360
CLA: 171720160409030719 (Gustavo de Geus)
2016-11-23 15:38:35 +01:00
Oliver Gierke
5bd0e21173 DATAMONGO-1527 - Updated changelog. 2016-11-23 13:52:43 +01:00
637 changed files with 36986 additions and 13105 deletions

View File

@@ -1,9 +1,12 @@
<!--
Thank you for proposing a pull request. This template will guide you through the essential steps necessary for a pull request.
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. Dont 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).
- [ ] You provide your full name and an email address registered with your GitHub account. If youre a first-time submitter, make sure you have completed the [Contributors License Agreement form](https://support.springsource.com/spring_committer_signup).

BIN
.mvn/wrapper/maven-wrapper.jar vendored Executable file

Binary file not shown.

1
.mvn/wrapper/maven-wrapper.properties vendored Executable file
View File

@@ -0,0 +1 @@
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip

View File

@@ -1,38 +0,0 @@
language: java
jdk:
- oraclejdk8
before_script:
- mongod --version
env:
matrix:
- PROFILE=ci
- PROFILE=mongo-next
- PROFILE=mongo3
- PROFILE=mongo3-next
- PROFILE=mongo31
- PROFILE=mongo32
- PROFILE=mongo33
- PROFILE=mongo34-next
# Current MongoDB version is 2.4.2 as of 2016-04, see https://github.com/travis-ci/travis-ci/issues/3694
# apt-get starts a MongoDB instance so it's not started using before_script
addons:
apt:
sources:
- mongodb-3.2-precise
packages:
- mongodb-org-server
- mongodb-org-shell
sudo: false
cache:
directories:
- $HOME/.m2
install: true
script: "mvn clean dependency:list test -P${PROFILE} -Dsort"

43
CI.adoc Normal file
View File

@@ -0,0 +1,43 @@
= Continuous Integration
image:https://jenkins.spring.io/buildStatus/icon?job=spring-data-mongodb%2Fmaster&subject=Moore%20(master)[link=https://jenkins.spring.io/view/SpringData/job/spring-data-mongodb/]
image:https://jenkins.spring.io/buildStatus/icon?job=spring-data-mongodb%2F2.1.x&subject=Lovelace%20(2.1.x)[link=https://jenkins.spring.io/view/SpringData/job/spring-data-mongodb/]
image:https://jenkins.spring.io/buildStatus/icon?job=spring-data-mongodb%2F1.10.x&subject=Ingalls%20(1.10.x)[link=https://jenkins.spring.io/view/SpringData/job/spring-data-mongodb/]
== Running CI tasks locally
Since this pipeline is purely Docker-based, it's easy to:
* Debug what went wrong on your local machine.
* Test out a a tweak to your test routine before sending it out.
* Experiment against a new image before submitting your pull request.
All of these use cases are great reasons to essentially run what the CI server does on your local machine.
IMPORTANT: To do this you must have Docker installed on your machine.
1. `docker run -it --mount type=bind,source="$(pwd)",target=/spring-data-mongodb-github springci/spring-data-openjdk8-with-mongodb-4.0:latest /bin/bash`
+
This will launch the Docker image and mount your source code at `spring-data-mongodb-github`.
+
2. `cd spring-data-mongodb-github`
+
Next, run the tests from inside the container:
+
3. `./mvnw clean dependency:list test -Dsort -Dbundlor.enabled=false -B` (or with whatever profile you need to test out)
Since the container is binding to your source, you can make edits from your IDE and continue to run build jobs.
If you need to package things up, do this:
1. `docker run -it --mount type=bind,source="$(pwd)",target=/spring-data-mongodb-github springci/spring-data-openjdk8-with-mongodb-4.0:latest /bin/bash`
+
This will launch the Docker image and mount your source code at `spring-data-mongodb-github`.
+
2. `cd spring-data-mongodb-github`
+
Next, package things from inside the container doing this:
+
3. `./mvnw clean dependency:list package -Dsort -Dbundlor.enabled=false -B`
NOTE: Docker containers can eat up disk space fast! From time to time, run `docker system prune` to clean out old images.

123
Jenkinsfile vendored Normal file
View File

@@ -0,0 +1,123 @@
pipeline {
agent none
triggers {
pollSCM 'H/10 * * * *'
upstream(upstreamProjects: "spring-data-commons/1.13.x", threshold: hudson.model.Result.SUCCESS)
}
options {
disableConcurrentBuilds()
buildDiscarder(logRotator(numToKeepStr: '14'))
}
stages {
stage("Test") {
when {
anyOf {
branch '1.10.x'
not { triggeredBy 'UpstreamCause' }
}
}
parallel {
stage("test: baseline") {
agent {
docker {
image 'springci/spring-data-openjdk8-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 clean dependency:list test -Dsort -U -B'
}
}
}
}
stage('Release to artifactory') {
when {
branch 'issue/*'
not { triggeredBy 'UpstreamCause' }
}
agent {
docker {
image 'adoptopenjdk/openjdk8:latest'
label 'data'
args '-v $HOME:/tmp/jenkins-home'
}
}
options { timeout(time: 20, unit: 'MINUTES') }
environment {
ARTIFACTORY = credentials('02bd1690-b54f-4c9f-819d-a77cb7a9822c')
}
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-1.10 " +
"-Dartifactory.build-number=${BUILD_NUMBER} " +
'-Dmaven.test.skip=true clean deploy -U -B'
}
}
stage('Release to artifactory with docs') {
when {
branch '1.10.x'
}
agent {
docker {
image 'adoptopenjdk/openjdk8:latest'
label 'data'
args '-v $HOME:/tmp/jenkins-home'
}
}
options { timeout(time: 20, unit: 'MINUTES') }
environment {
ARTIFACTORY = credentials('02bd1690-b54f-4c9f-819d-a77cb7a9822c')
}
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-1.10 " +
"-Dartifactory.build-number=${BUILD_NUMBER} " +
'-Dmaven.test.skip=true clean deploy -U -B'
}
}
}
post {
changed {
script {
slackSend(
color: (currentBuild.currentResult == 'SUCCESS') ? 'good' : 'danger',
channel: '#spring-data-dev',
message: "${currentBuild.fullDisplayName} - `${currentBuild.currentResult}`\n${env.BUILD_URL}")
emailext(
subject: "[${currentBuild.fullDisplayName}] ${currentBuild.currentResult}",
mimeType: 'text/html',
recipientProviders: [[$class: 'CulpritsRecipientProvider'], [$class: 'RequesterRecipientProvider']],
body: "<a href=\"${env.BUILD_URL}\">${currentBuild.fullDisplayName} is reported as ${currentBuild.currentResult}</a>")
}
}
}
}

159
README.adoc Normal file
View File

@@ -0,0 +1,159 @@
image:https://spring.io/badges/spring-data-mongodb/ga.svg[Spring Data MongoDB,link=https://projects.spring.io/spring-data-mongodb#quick-start] image:https://spring.io/badges/spring-data-mongodb/snapshot.svg[Spring Data MongoDB,link=https://projects.spring.io/spring-data-mongodb#quick-start]
= Spring Data MongoDB image:https://jenkins.spring.io/buildStatus/icon?job=spring-data-mongodb%2Fmaster&subject=Build[link=https://jenkins.spring.io/view/SpringData/job/spring-data-mongodb/] https://gitter.im/spring-projects/spring-data[image:https://badges.gitter.im/spring-projects/spring-data.svg[Gitter]]
The primary goal of the https://projects.spring.io/spring-data[Spring Data] project is to make it easier to build Spring-powered applications that use new data access technologies such as non-relational databases, map-reduce frameworks, and cloud based data services.
The Spring Data MongoDB project aims to provide a familiar and consistent Spring-based programming model for new datastores while retaining store-specific features and capabilities.
The Spring Data MongoDB project provides integration with the MongoDB document database.
Key functional areas of Spring Data MongoDB are a POJO centric model for interacting with a MongoDB `+Document+` and easily writing a repository style data access layer.
== 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.
== Getting Started
Here is a quick teaser of an application using Spring Data Repositories in Java:
[source,java]
----
public interface PersonRepository extends CrudRepository<Person, Long> {
List<Person> findByLastname(String lastname);
List<Person> findByFirstnameLike(String firstname);
}
@Service
public class MyService {
private final PersonRepository repository;
public MyService(PersonRepository repository) {
this.repository = repository;
}
public void doWork() {
repository.deleteAll();
Person person = new Person();
person.setFirstname("Oliver");
person.setLastname("Gierke");
repository.save(person);
List<Person> lastNameResults = repository.findByLastname("Gierke");
List<Person> firstNameResults = repository.findByFirstnameLike("Oli*");
}
}
@Configuration
@EnableMongoRepositories
class ApplicationConfig extends AbstractMongoConfiguration {
@Override
public MongoClient mongoClient() {
return new MongoClient();
}
@Override
protected String getDatabaseName() {
return "springdata";
}
}
----
=== Maven configuration
Add the Maven dependency:
[source,xml]
----
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>${version}.RELEASE</version>
</dependency>
----
If you'd rather like the latest snapshots of the upcoming major version, use our Maven snapshot repository and declare the appropriate dependency version.
[source,xml]
----
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>${version}.BUILD-SNAPSHOT</version>
</dependency>
<repository>
<id>spring-libs-snapshot</id>
<name>Spring Snapshot Repository</name>
<url>https://repo.spring.io/libs-snapshot</url>
</repository>
----
== Getting Help
Having trouble with Spring Data? Wed love to help!
* Check the
https://docs.spring.io/spring-data/mongodb/docs/current/reference/html/[reference documentation], and https://docs.spring.io/spring-data/mongodb/docs/current/api/[Javadocs].
* Learn the Spring basics Spring Data builds on Spring Framework, check the https://spring.io[spring.io] web-site for a wealth of reference documentation.
If you are just starting out with Spring, try one of the https://spring.io/guides[guides].
* If you are upgrading, check out the https://docs.spring.io/spring-data/mongodb/docs/current/changelog.txt[changelog] for "`new and noteworthy`" features.
* Ask a question - we monitor https://stackoverflow.com[stackoverflow.com] for questions tagged with https://stackoverflow.com/tags/spring-data[`spring-data-mongodb`].
You can also chat with the community on https://gitter.im/spring-projects/spring-data[Gitter].
* Report bugs with Spring Data MongoDB at https://jira.spring.io/browse/DATAMONGO[jira.spring.io/browse/DATAMONGO].
== Reporting Issues
Spring Data uses JIRA as issue tracking system to record bugs and feature requests. If you want to raise an issue, please follow the recommendations below:
* Before you log a bug, please search the
https://jira.spring.io/browse/DATAMONGO[issue tracker] to see if someone has already reported the problem.
* If the issue doesnt already exist, https://jira.spring.io/browse/DATAMONGO[create a new issue].
* Please provide as much information as possible with the issue report, we like to know the version of Spring Data that you are using and JVM version.
* If you need to paste code, or include a stack trace use JIRA `{code}…{code}` escapes before and after your text.
* If possible try to create a test-case or project that replicates the issue. Attach a link to your code or a compressed file containing your code.
== Building from Source
You dont need to build from source to use Spring Data (binaries in https://repo.spring.io[repo.spring.io]), but if you want to try out the latest and greatest, Spring Data can be easily built with the https://github.com/takari/maven-wrapper[maven wrapper].
You also need JDK 1.8.
[source,bash]
----
$ ./mvnw clean install
----
If you want to build with the regular `mvn` command, you will need https://maven.apache.org/run-maven/index.html[Maven v3.5.0 or above].
_Also see link:CONTRIBUTING.adoc[CONTRIBUTING.adoc] if you wish to submit pull requests, and in particular please sign the https://cla.pivotal.io/sign/spring[Contributors Agreement] before your first non-trivial change._
=== Building reference documentation
Building the documentation builds also the project without running tests.
[source,bash]
----
$ ./mvnw clean install -Pdistribute
----
The generated documentation is available from `target/site/reference/html/index.html`.
== Guides
The https://spring.io/[spring.io] site contains several guides that show how to use Spring Data step-by-step:
* https://spring.io/guides/gs/accessing-data-mongodb/[Accessing Data with MongoDB] is a very basic guide that shows you how to create a simple application and how to access data using repositories.
* https://spring.io/guides/gs/accessing-mongodb-data-rest/[Accessing MongoDB Data with REST] is a guide to creating a REST web service exposing data stored in MongoDB through repositories.
== Examples
* https://github.com/spring-projects/spring-data-examples/[Spring Data Examples] contains example projects that explain specific features in more detail.
== License
Spring Data MongoDB is Open Source software released under the https://www.apache.org/licenses/LICENSE-2.0.html[Apache 2.0 license].

150
README.md
View File

@@ -1,150 +0,0 @@
[![Spring Data MongoDB](https://spring.io/badges/spring-data-mongodb/ga.svg)](http://projects.spring.io/spring-data-mongodb#quick-start)
[![Spring Data MongoDB](https://spring.io/badges/spring-data-mongodb/snapshot.svg)](http://projects.spring.io/spring-data-mongodb#quick-start)
# Spring Data MongoDB
The primary goal of the [Spring Data](http://projects.spring.io/spring-data) project is to make it easier to build Spring-powered applications that use new data access technologies such as non-relational databases, map-reduce frameworks, and cloud based data services.
The Spring Data MongoDB project aims to provide a familiar and consistent Spring-based programming model for new datastores while retaining store-specific features and capabilities. The Spring Data MongoDB project provides integration with the MongoDB document database. Key functional areas of Spring Data MongoDB are a POJO centric model for interacting with a MongoDB DBCollection and easily writing a repository style data access layer.
## Getting Help
For a comprehensive treatment of all the Spring Data MongoDB features, please refer to:
* the [User Guide](http://docs.spring.io/spring-data/mongodb/docs/current/reference/html/)
* the [JavaDocs](http://docs.spring.io/spring-data/mongodb/docs/current/api/) have extensive comments in them as well.
* the home page of [Spring Data MongoDB](http://projects.spring.io/spring-data-mongodb) contains links to articles and other resources.
* for more detailed questions, use [Spring Data Mongodb on Stackoverflow](http://stackoverflow.com/questions/tagged/spring-data-mongodb).
If you are new to Spring as well as to Spring Data, look for information about [Spring projects](http://projects.spring.io/).
## Quick Start
### Maven configuration
Add the Maven dependency:
```xml
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>${version}.RELEASE</version>
</dependency>
```
If you'd rather like the latest snapshots of the upcoming major version, use our Maven snapshot repository and declare the appropriate dependency version.
```xml
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>${version}.BUILD-SNAPSHOT</version>
</dependency>
<repository>
<id>spring-libs-snapshot</id>
<name>Spring Snapshot Repository</name>
<url>http://repo.spring.io/libs-snapshot</url>
</repository>
```
### MongoTemplate
MongoTemplate is the central support class for Mongo database operations. It provides:
* Basic POJO mapping support to and from BSON
* Convenience methods to interact with the store (insert object, update objects) and MongoDB specific ones (geo-spatial operations, upserts, map-reduce etc.)
* Connection affinity callback
* Exception translation into Spring's [technology agnostic DAO exception hierarchy](http://docs.spring.io/spring/docs/current/spring-framework-reference/html/dao.html#dao-exceptions).
### Spring Data repositories
To simplify the creation of data repositories Spring Data MongoDB provides a generic repository programming model. It will automatically create a repository proxy for you that adds implementations of finder methods you specify on an interface.
For example, given a `Person` class with first and last name properties, a `PersonRepository` interface that can query for `Person` by last name and when the first name matches a like expression is shown below:
```java
public interface PersonRepository extends CrudRepository<Person, Long> {
List<Person> findByLastname(String lastname);
List<Person> findByFirstnameLike(String firstname);
}
```
The queries issued on execution will be derived from the method name. Extending `CrudRepository` causes CRUD methods being pulled into the interface so that you can easily save and find single entities and collections of them.
You can have Spring automatically create a proxy for the interface by using the following JavaConfig:
```java
@Configuration
@EnableMongoRepositories
class ApplicationConfig extends AbstractMongoConfiguration {
@Override
public Mongo mongo() throws Exception {
return new MongoClient();
}
@Override
protected String getDatabaseName() {
return "springdata";
}
}
```
This sets up a connection to a local MongoDB instance and enables the detection of Spring Data repositories (through `@EnableMongoRepositories`). The same configuration would look like this in XML:
```xml
<bean id="template" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg>
<bean class="com.mongodb.MongoClient">
<constructor-arg value="localhost" />
<constructor-arg value="27017" />
</bean>
</constructor-arg>
<constructor-arg value="database" />
</bean>
<mongo:repositories base-package="com.acme.repository" />
```
This will find the repository interface and register a proxy object in the container. You can use it as shown below:
```java
@Service
public class MyService {
private final PersonRepository repository;
@Autowired
public MyService(PersonRepository repository) {
this.repository = repository;
}
public void doWork() {
repository.deleteAll();
Person person = new Person();
person.setFirstname("Oliver");
person.setLastname("Gierke");
person = repository.save(person);
List<Person> lastNameResults = repository.findByLastname("Gierke");
List<Person> firstNameResults = repository.findByFirstnameLike("Oli*");
}
}
```
## Contributing to Spring Data
Here are some ways for you to get involved in the community:
* Get involved with the Spring community on Stackoverflow and help out on the [spring-data-mongodb](http://stackoverflow.com/questions/tagged/spring-data-mongodb) tag by responding to questions and joining the debate.
* Create [JIRA](https://jira.springframework.org/browse/DATADOC) tickets for bugs and new features and comment and vote on the ones that you are interested in.
* Github is for social coding: if you want to write code, we encourage contributions through pull requests from [forks of this repository](http://help.github.com/forking/). If you want to contribute code this way, please reference a JIRA ticket as well covering the specific issue you are addressing.
* Watch for upcoming articles on Spring by [subscribing](http://spring.io/blog) to spring.io.
Before we accept a non-trivial patch or pull request we will need you to sign the [contributor's agreement](https://support.springsource.com/spring_committer_signup). Signing the contributor's agreement does not grant anyone commit rights to the main repository, but it does mean that we can accept your contributions, and you will get an author credit if we do. Active contributors might be asked to join the core team, and given the ability to merge pull requests.

View File

@@ -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 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/*

View File

@@ -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 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/*

2
lombok.config Normal file
View File

@@ -0,0 +1,2 @@
lombok.nonNull.exceptionType = IllegalArgumentException
lombok.log.fieldName = LOG

286
mvnw vendored Executable file
View File

@@ -0,0 +1,286 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Maven2 Start Up Batch script
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# M2_HOME - location of maven2's installed home dir
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "`uname`" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true;;
Darwin*) darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
export JAVA_HOME="`/usr/libexec/java_home`"
else
export JAVA_HOME="/Library/Java/Home"
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=`java-config --jre-home`
fi
fi
if [ -z "$M2_HOME" ] ; then
## resolve links - $0 may be a link to maven's home
PRG="$0"
# need this for relative symlinks
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG="`dirname "$PRG"`/$link"
fi
done
saveddir=`pwd`
M2_HOME=`dirname "$PRG"`/..
# make it fully qualified
M2_HOME=`cd "$M2_HOME" && pwd`
cd "$saveddir"
# echo Using m2 at $M2_HOME
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --unix "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
[ -n "$M2_HOME" ] &&
M2_HOME="`(cd "$M2_HOME"; pwd)`"
[ -n "$JAVA_HOME" ] &&
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
# TODO classpath?
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="`which javac`"
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=`which readlink`
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
if $darwin ; then
javaHome="`dirname \"$javaExecutable\"`"
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
else
javaExecutable="`readlink -f \"$javaExecutable\"`"
fi
javaHome="`dirname \"$javaExecutable\"`"
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="`which java`"
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]
then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=`cd "$wdir/.."; pwd`
fi
# end of workaround
done
echo "${basedir}"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
echo "$(tr -s '\n' ' ' < "$1")"
fi
}
BASE_DIR=`find_maven_basedir "$(pwd)"`
if [ -z "$BASE_DIR" ]; then
exit 1;
fi
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found .mvn/wrapper/maven-wrapper.jar"
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
fi
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
while IFS="=" read key value; do
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
esac
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
if [ "$MVNW_VERBOSE" = true ]; then
echo "Downloading from: $jarUrl"
fi
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
if command -v wget > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found wget ... using wget"
fi
wget "$jarUrl" -O "$wrapperJarPath"
elif command -v curl > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found curl ... using curl"
fi
curl -o "$wrapperJarPath" "$jarUrl"
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Falling back to using Java to download"
fi
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
if [ -e "$javaClass" ]; then
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Compiling MavenWrapperDownloader.java ..."
fi
# Compiling the Java class
("$JAVA_HOME/bin/javac" "$javaClass")
fi
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
# Running the downloader
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Running MavenWrapperDownloader.java ..."
fi
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
fi
fi
fi
fi
##########################################################################################
# End of extension
##########################################################################################
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
if [ "$MVNW_VERBOSE" = true ]; then
echo $MAVEN_PROJECTBASEDIR
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --path --windows "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
fi
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \
$MAVEN_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

161
mvnw.cmd vendored Executable file
View File

@@ -0,0 +1,161 @@
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM https://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven2 Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
echo Found %WRAPPER_JAR%
) else (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %DOWNLOAD_URL%
powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"
echo Finished downloading %WRAPPER_JAR%
)
@REM End of extension
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%" == "on" pause
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
exit /B %ERROR_CODE%

52
pom.xml
View File

@@ -1,21 +1,21 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>1.10.0.BUILD-SNAPSHOT</version>
<version>1.10.24.BUILD-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Spring Data MongoDB</name>
<description>MongoDB support for Spring Data</description>
<url>http://projects.spring.io/spring-data-mongodb</url>
<url>https://projects.spring.io/spring-data-mongodb</url>
<parent>
<groupId>org.springframework.data.build</groupId>
<artifactId>spring-data-parent</artifactId>
<version>1.9.0.BUILD-SNAPSHOT</version>
<version>1.9.24.BUILD-SNAPSHOT</version>
</parent>
<modules>
@@ -28,9 +28,10 @@
<properties>
<project.type>multi</project.type>
<dist.id>spring-data-mongodb</dist.id>
<springdata.commons>1.13.0.BUILD-SNAPSHOT</springdata.commons>
<springdata.commons>1.13.24.BUILD-SNAPSHOT</springdata.commons>
<mongo>2.14.3</mongo>
<mongo.osgi>2.13.0</mongo.osgi>
<jmh.version>1.19</jmh.version>
</properties>
<developers>
@@ -39,7 +40,7 @@
<name>Oliver Gierke</name>
<email>ogierke at gopivotal.com</email>
<organization>Pivotal</organization>
<organizationUrl>http://www.gopivotal.com</organizationUrl>
<organizationUrl>https://pivotal.io</organizationUrl>
<roles>
<role>Project Lead</role>
</roles>
@@ -50,7 +51,7 @@
<name>Thomas Risberg</name>
<email>trisberg at vmware.com</email>
<organization>Pivotal</organization>
<organizationUrl>http://www.gopivotal.com</organizationUrl>
<organizationUrl>https://pivotal.io</organizationUrl>
<roles>
<role>Developer</role>
</roles>
@@ -61,7 +62,7 @@
<name>Mark Pollack</name>
<email>mpollack at gopivotal.com</email>
<organization>Pivotal</organization>
<organizationUrl>http://www.gopivotal.com</organizationUrl>
<organizationUrl>https://pivotal.io</organizationUrl>
<roles>
<role>Developer</role>
</roles>
@@ -72,7 +73,7 @@
<name>Jon Brisbin</name>
<email>jbrisbin at gopivotal.com</email>
<organization>Pivotal</organization>
<organizationUrl>http://www.gopivotal.com</organizationUrl>
<organizationUrl>https://pivotal.io</organizationUrl>
<roles>
<role>Developer</role>
</roles>
@@ -83,7 +84,7 @@
<name>Thomas Darimont</name>
<email>tdarimont at gopivotal.com</email>
<organization>Pivotal</organization>
<organizationUrl>http://www.gopivotal.com</organizationUrl>
<organizationUrl>https://pivotal.io</organizationUrl>
<roles>
<role>Developer</role>
</roles>
@@ -94,7 +95,7 @@
<name>Christoph Strobl</name>
<email>cstrobl at gopivotal.com</email>
<organization>Pivotal</organization>
<organizationUrl>http://www.gopivotal.com</organizationUrl>
<organizationUrl>https://pivotal.io</organizationUrl>
<roles>
<role>Developer</role>
</roles>
@@ -178,11 +179,20 @@
</profile>
<profile>
<id>mongo34</id>
<properties>
<mongo>3.4.0</mongo>
</properties>
</profile>
<profile>
<id>mongo34-next</id>
<properties>
<mongo>3.4.0-SNAPSHOT</mongo>
<mongo>3.4.1-SNAPSHOT</mongo>
</properties>
<repositories>
@@ -195,16 +205,14 @@
</profile>
<profile>
<id>release</id>
<build>
<plugins>
<plugin>
<groupId>org.jfrog.buildinfo</groupId>
<artifactId>artifactory-maven-plugin</artifactId>
<inherited>false</inherited>
</plugin>
</plugins>
</build>
<id>benchmarks</id>
<modules>
<module>spring-data-mongodb</module>
<module>spring-data-mongodb-cross-store</module>
<module>spring-data-mongodb-log4j</module>
<module>spring-data-mongodb-distribution</module>
<module>spring-data-mongodb-benchmarks</module>
</modules>
</profile>
</profiles>

View File

@@ -0,0 +1,76 @@
# Benchmarks
Benchmarks are based on [JMH](http://openjdk.java.net/projects/code-tools/jmh/).
# Running Benchmarks
Running benchmarks is disabled by default and can be activated via the `benchmarks` profile.
To run the benchmarks with default settings use.
```bash
mvn -P benchmarks clean test
```
A basic report will be printed to the CLI.
```bash
# Run complete. Total time: 00:00:15
Benchmark Mode Cnt Score Error Units
MappingMongoConverterBenchmark.readObject thrpt 10 1920157,631 ± 64310,809 ops/s
MappingMongoConverterBenchmark.writeObject thrpt 10 782732,857 ± 53804,130 ops/s
```
## Running all Benchmarks of a specific class
To run all Benchmarks of a specific class, just provide its simple class name via the `benchmark` command line argument.
```bash
mvn -P benchmarks clean test -D benchmark=MappingMongoConverterBenchmark
```
## Running a single Benchmark
To run a single Benchmark provide its containing class simple name followed by `#` and the method name via the `benchmark` command line argument.
```bash
mvn -P benchmarks clean test -D benchmark=MappingMongoConverterBenchmark#readObjectWith2Properties
```
# Saving Benchmark Results
A detailed benchmark report is stored in JSON format in the `/target/reports/performance` directory.
To store the report in a different location use the `benchmarkReportDir` command line argument.
## MongoDB
Results can be directly piped to MongoDB by providing a valid [Connection String](https://docs.mongodb.com/manual/reference/connection-string/) via the `publishTo` command line argument.
```bash
mvn -P benchmarks clean test -D publishTo=mongodb://127.0.0.1:27017
```
NOTE: If the uri does not explicitly define a database the default `spring-data-mongodb-benchmarks` is used.
## HTTP Endpoint
The benchmark report can also be posted as `application/json` to an HTTP Endpoint by providing a valid URl via the `publishTo` command line argument.
```bash
mvn -P benchmarks clean test -D publishTo=http://127.0.0.1:8080/capture-benchmarks
```
# Customizing Benchmarks
Following options can be set via command line.
Option | Default Value
--- | ---
warmupIterations | 10
warmupTime | 1 (seconds)
measurementIterations | 10
measurementTime | 1 (seconds)
forks | 1
benchmarkReportDir | /target/reports/performance (always relative to project root dir)
benchmark | .* (single benchmark via `classname#benchmark`)
publishTo | \[not set\] (mongodb-uri or http-endpoint)

View File

@@ -0,0 +1,112 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>1.10.24.BUILD-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>spring-data-mongodb-benchmarks</artifactId>
<packaging>jar</packaging>
<name>Spring Data MongoDB - Microbenchmarks</name>
<properties>
<!-- Skip tests by default; run only if -DskipTests=false is specified or benchmarks profile is activated -->
<skipTests>true</skipTests>
<bundlor.enabled>false</bundlor.enabled>
</properties>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>${jmh.version}</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>${jmh.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>benchmarks</id>
<properties>
<skipTests>false</skipTests>
</properties>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
<version>2.2.2</version>
<executions>
<execution>
<goals>
<goal>revision</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>default-jar</id>
<phase>never</phase>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<testSourceDirectory>${project.build.sourceDirectory}</testSourceDirectory>
<testClassesDirectory>${project.build.outputDirectory}</testClassesDirectory>
<excludes>
<exclude>**/AbstractMicrobenchmark.java</exclude>
<exclude>**/*$*.class</exclude>
<exclude>**/generated/*.class</exclude>
</excludes>
<includes>
<include>**/*Benchmark*</include>
</includes>
<systemPropertyVariables>
<benchmarkReportDir>${project.build.directory}/reports/performance</benchmarkReportDir>
<project.version>${project.version}</project.version>
<git.dirty>${git.dirty}</git.dirty>
<git.commit.id>${git.commit.id}</git.commit.id>
<git.branch>${git.branch}</git.branch>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,111 @@
/*
* Copyright 2017-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.convert;
import static org.springframework.data.mongodb.core.query.Criteria.*;
import static org.springframework.data.mongodb.core.query.Query.*;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
import org.bson.types.ObjectId;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.mapping.DBRef;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.microbenchmark.AbstractMicrobenchmark;
import com.mongodb.MongoClient;
import com.mongodb.ServerAddress;
/**
* @author Christoph Strobl
*/
@State(Scope.Benchmark)
public class DbRefMappingBenchmark extends AbstractMicrobenchmark {
private static final String DB_NAME = "dbref-loading-benchmark";
private MongoClient client;
private MongoTemplate template;
private Query queryObjectWithDBRef;
private Query queryObjectWithDBRefList;
@Setup
public void setUp() throws Exception {
client = new MongoClient(new ServerAddress());
template = new MongoTemplate(client, DB_NAME);
List<RefObject> refObjects = new ArrayList<RefObject>();
for (int i = 0; i < 1; i++) {
RefObject o = new RefObject();
template.save(o);
refObjects.add(o);
}
ObjectWithDBRef singleDBRef = new ObjectWithDBRef();
singleDBRef.ref = refObjects.iterator().next();
template.save(singleDBRef);
ObjectWithDBRef multipleDBRefs = new ObjectWithDBRef();
multipleDBRefs.refList = refObjects;
template.save(multipleDBRefs);
queryObjectWithDBRef = query(where("id").is(singleDBRef.id));
queryObjectWithDBRefList = query(where("id").is(multipleDBRefs.id));
}
@TearDown
public void tearDown() {
client.dropDatabase(DB_NAME);
client.close();
}
@Benchmark // DATAMONGO-1720
public ObjectWithDBRef readSingleDbRef() {
return template.findOne(queryObjectWithDBRef, ObjectWithDBRef.class);
}
@Benchmark // DATAMONGO-1720
public ObjectWithDBRef readMultipleDbRefs() {
return template.findOne(queryObjectWithDBRefList, ObjectWithDBRef.class);
}
@Data
static class ObjectWithDBRef {
private @Id ObjectId id;
private @DBRef RefObject ref;
private @DBRef List<RefObject> refList;
}
@Data
static class RefObject {
private @Id String id;
private String someValue;
}
}

View File

@@ -0,0 +1,182 @@
/*
* Copyright 2017-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.convert;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.bson.types.ObjectId;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.springframework.data.annotation.Id;
import org.springframework.data.geo.Point;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
import org.springframework.data.mongodb.core.mapping.Field;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.mongodb.microbenchmark.AbstractMicrobenchmark;
import com.mongodb.BasicDBObject;
import com.mongodb.MongoClient;
import com.mongodb.ServerAddress;
import com.mongodb.util.JSON;
/**
* @author Christoph Strobl
*/
@State(Scope.Benchmark)
public class MappingMongoConverterBenchmark extends AbstractMicrobenchmark {
private static final String DB_NAME = "mapping-mongo-converter-benchmark";
private MongoClient client;
private MongoMappingContext mappingContext;
private MappingMongoConverter converter;
private BasicDBObject documentWith2Properties, documentWith2PropertiesAnd1Nested;
private Customer objectWith2PropertiesAnd1Nested;
private BasicDBObject documentWithFlatAndComplexPropertiesPlusListAndMap;
private SlightlyMoreComplexObject objectWithFlatAndComplexPropertiesPlusListAndMap;
@Setup
public void setUp() throws Exception {
client = new MongoClient(new ServerAddress());
this.mappingContext = new MongoMappingContext();
this.mappingContext.setInitialEntitySet(Collections.singleton(Customer.class));
this.mappingContext.afterPropertiesSet();
DbRefResolver dbRefResolver = new DefaultDbRefResolver(new SimpleMongoDbFactory(client, DB_NAME));
this.converter = new MappingMongoConverter(dbRefResolver, mappingContext);
this.converter.setCustomConversions(new CustomConversions(Collections.emptyList()));
this.converter.afterPropertiesSet();
// just a flat document
this.documentWith2Properties = new BasicDBObject("firstname", "Dave").append("lastname", "Matthews");
// document with a nested one
BasicDBObject address = new BasicDBObject("zipCode", "ABCDE").append("city", "Some Place");
this.documentWith2PropertiesAnd1Nested = new BasicDBObject("firstname", "Dave").//
append("lastname", "Matthews").//
append("address", address);
// object equivalent of documentWith2PropertiesAnd1Nested
this.objectWith2PropertiesAnd1Nested = new Customer("Dave", "Matthews", new Address("zipCode", "City"));
// a bit more challenging object with list & map conversion.
objectWithFlatAndComplexPropertiesPlusListAndMap = new SlightlyMoreComplexObject();
objectWithFlatAndComplexPropertiesPlusListAndMap.id = UUID.randomUUID().toString();
objectWithFlatAndComplexPropertiesPlusListAndMap.addressList = Arrays.asList(new Address("zip-1", "city-1"),
new Address("zip-2", "city-2"));
objectWithFlatAndComplexPropertiesPlusListAndMap.customer = objectWith2PropertiesAnd1Nested;
objectWithFlatAndComplexPropertiesPlusListAndMap.customerMap = new LinkedHashMap<String, Customer>();
objectWithFlatAndComplexPropertiesPlusListAndMap.customerMap.put("dave", objectWith2PropertiesAnd1Nested);
objectWithFlatAndComplexPropertiesPlusListAndMap.customerMap.put("deborah",
new Customer("Deborah Anne", "Dyer", new Address("?", "london")));
objectWithFlatAndComplexPropertiesPlusListAndMap.customerMap.put("eddie",
new Customer("Eddie", "Vedder", new Address("??", "Seattle")));
objectWithFlatAndComplexPropertiesPlusListAndMap.intOne = Integer.MIN_VALUE;
objectWithFlatAndComplexPropertiesPlusListAndMap.intTwo = Integer.MAX_VALUE;
objectWithFlatAndComplexPropertiesPlusListAndMap.location = new Point(-33.865143, 151.209900);
objectWithFlatAndComplexPropertiesPlusListAndMap.renamedField = "supercalifragilisticexpialidocious";
objectWithFlatAndComplexPropertiesPlusListAndMap.stringOne = "¯\\_(ツ)_/¯";
objectWithFlatAndComplexPropertiesPlusListAndMap.stringTwo = " (╯°□°)╯︵ ┻━┻";
// JSON equivalent of objectWithFlatAndComplexPropertiesPlusListAndMap
documentWithFlatAndComplexPropertiesPlusListAndMap = (BasicDBObject) JSON.parse(
"{ \"_id\" : \"517f6aee-e9e0-44f0-88ed-f3694a019f27\", \"intOne\" : -2147483648, \"intTwo\" : 2147483647, \"stringOne\" : \"¯\\\\_(ツ)_/¯\", \"stringTwo\" : \" (╯°□°)╯︵ ┻━┻\", \"explicit-field-name\" : \"supercalifragilisticexpialidocious\", \"location\" : { \"x\" : -33.865143, \"y\" : 151.2099 }, \"objectWith2PropertiesAnd1Nested\" : { \"firstname\" : \"Dave\", \"lastname\" : \"Matthews\", \"address\" : { \"zipCode\" : \"zipCode\", \"city\" : \"City\" } }, \"addressList\" : [{ \"zipCode\" : \"zip-1\", \"city\" : \"city-1\" }, { \"zipCode\" : \"zip-2\", \"city\" : \"city-2\" }], \"customerMap\" : { \"dave\" : { \"firstname\" : \"Dave\", \"lastname\" : \"Matthews\", \"address\" : { \"zipCode\" : \"zipCode\", \"city\" : \"City\" } }, \"deborah\" : { \"firstname\" : \"Deborah Anne\", \"lastname\" : \"Dyer\", \"address\" : { \"zipCode\" : \"?\", \"city\" : \"london\" } }, \"eddie\" : { \"firstname\" : \"Eddie\", \"lastname\" : \"Vedder\", \"address\" : { \"zipCode\" : \"??\", \"city\" : \"Seattle\" } } }, \"_class\" : \"org.springframework.data.mongodb.core.convert.MappingMongoConverterBenchmark$SlightlyMoreComplexObject\" }");
}
@TearDown
public void tearDown() {
client.dropDatabase(DB_NAME);
client.close();
}
@Benchmark // DATAMONGO-1720
public Customer readObjectWith2Properties() {
return converter.read(Customer.class, documentWith2Properties);
}
@Benchmark // DATAMONGO-1720
public Customer readObjectWith2PropertiesAnd1NestedObject() {
return converter.read(Customer.class, documentWith2PropertiesAnd1Nested);
}
@Benchmark // DATAMONGO-1720
public BasicDBObject writeObjectWith2PropertiesAnd1NestedObject() {
BasicDBObject sink = new BasicDBObject();
converter.write(objectWith2PropertiesAnd1Nested, sink);
return sink;
}
@Benchmark // DATAMONGO-1720
public Object readObjectWithListAndMapsOfComplexType() {
return converter.read(SlightlyMoreComplexObject.class, documentWithFlatAndComplexPropertiesPlusListAndMap);
}
@Benchmark // DATAMONGO-1720
public Object writeObjectWithListAndMapsOfComplexType() {
BasicDBObject sink = new BasicDBObject();
converter.write(objectWithFlatAndComplexPropertiesPlusListAndMap, sink);
return sink;
}
@Getter
@RequiredArgsConstructor
static class Customer {
private @Id ObjectId id;
private final String firstname, lastname;
private final Address address;
}
@Getter
@AllArgsConstructor
static class Address {
private String zipCode, city;
}
@Data
static class SlightlyMoreComplexObject {
@Id String id;
int intOne, intTwo;
String stringOne, stringTwo;
@Field("explicit-field-name") String renamedField;
Point location;
Customer customer;
List<Address> addressList;
Map<String, Customer> customerMap;
}
}

View File

@@ -0,0 +1,329 @@
/*
* Copyright 2017-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.microbenchmark;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import org.junit.Test;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;
import org.openjdk.jmh.results.RunResult;
import org.openjdk.jmh.results.format.ResultFormatType;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.options.ChainedOptionsBuilder;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import org.openjdk.jmh.runner.options.TimeValue;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.data.mongodb.microbenchmark.ResultsWriter.Utils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;
/**
* @author Christoph Strobl
*/
@Warmup(iterations = AbstractMicrobenchmark.WARMUP_ITERATIONS)
@Measurement(iterations = AbstractMicrobenchmark.MEASUREMENT_ITERATIONS)
@Fork(AbstractMicrobenchmark.FORKS)
@State(Scope.Thread)
public class AbstractMicrobenchmark {
static final int WARMUP_ITERATIONS = 5;
static final int MEASUREMENT_ITERATIONS = 10;
static final int FORKS = 1;
static final String[] JVM_ARGS = { "-server", "-XX:+HeapDumpOnOutOfMemoryError", "-Xms1024m", "-Xmx1024m",
"-XX:MaxDirectMemorySize=1024m" };
private final StandardEnvironment environment = new StandardEnvironment();
/**
* Run matching {@link org.openjdk.jmh.annotations.Benchmark} methods with options collected from
* {@link org.springframework.core.env.Environment}.
*
* @throws Exception
* @see #options(String)
*/
@Test
public void run() throws Exception {
String includes = includes();
if (!includes.contains(org.springframework.util.ClassUtils.getShortName(getClass()))) {
return;
}
publishResults(new Runner(options(includes).build()).run());
}
/**
* Get the regex for all benchmarks to be included in the run. By default every benchmark within classes matching the
* current ones short name. <br />
* The {@literal benchmark} command line argument allows overriding the defaults using {@code #} as class / method
* name separator.
*
* @return never {@literal null}.
* @see org.springframework.util.ClassUtils#getShortName(Class)
*/
protected String includes() {
String tests = environment.getProperty("benchmark", String.class);
if (!StringUtils.hasText(tests)) {
return ".*" + org.springframework.util.ClassUtils.getShortName(getClass()) + ".*";
}
if (!tests.contains("#")) {
return ".*" + tests + ".*";
}
String[] args = tests.split("#");
return ".*" + args[0] + "." + args[1];
}
/**
* Collect all options for the {@link Runner}.
*
* @param includes regex for matching benchmarks to be included in the run.
* @return never {@literal null}.
* @throws Exception
*/
protected ChainedOptionsBuilder options(String includes) throws Exception {
ChainedOptionsBuilder optionsBuilder = new OptionsBuilder().include(includes).jvmArgs(jvmArgs());
optionsBuilder = warmup(optionsBuilder);
optionsBuilder = measure(optionsBuilder);
optionsBuilder = forks(optionsBuilder);
optionsBuilder = report(optionsBuilder);
return optionsBuilder;
}
/**
* JVM args to apply to {@link Runner} via its {@link org.openjdk.jmh.runner.options.Options}.
*
* @return {@link #JVM_ARGS} by default.
*/
protected String[] jvmArgs() {
String[] args = new String[JVM_ARGS.length];
System.arraycopy(JVM_ARGS, 0, args, 0, JVM_ARGS.length);
return args;
}
/**
* Read {@code warmupIterations} property from {@link org.springframework.core.env.Environment}.
*
* @return -1 if not set.
*/
protected int getWarmupIterations() {
return environment.getProperty("warmupIterations", Integer.class, -1);
}
/**
* Read {@code measurementIterations} property from {@link org.springframework.core.env.Environment}.
*
* @return -1 if not set.
*/
protected int getMeasurementIterations() {
return environment.getProperty("measurementIterations", Integer.class, -1);
}
/**
* Read {@code forks} property from {@link org.springframework.core.env.Environment}.
*
* @return -1 if not set.
*/
protected int getForksCount() {
return environment.getProperty("forks", Integer.class, -1);
}
/**
* Read {@code benchmarkReportDir} property from {@link org.springframework.core.env.Environment}.
*
* @return {@literal null} if not set.
*/
protected String getReportDirectory() {
return environment.getProperty("benchmarkReportDir");
}
/**
* Read {@code measurementTime} property from {@link org.springframework.core.env.Environment}.
*
* @return -1 if not set.
*/
protected long getMeasurementTime() {
return environment.getProperty("measurementTime", Long.class, -1L);
}
/**
* Read {@code warmupTime} property from {@link org.springframework.core.env.Environment}.
*
* @return -1 if not set.
*/
protected long getWarmupTime() {
return environment.getProperty("warmupTime", Long.class, -1L);
}
/**
* {@code project.version_yyyy-MM-dd_ClassName.json} eg.
* {@literal 1.11.0.BUILD-SNAPSHOT_2017-03-07_MappingMongoConverterBenchmark.json}
*
* @return
*/
protected String reportFilename() {
StringBuilder sb = new StringBuilder();
if (environment.containsProperty("project.version")) {
sb.append(environment.getProperty("project.version"));
sb.append("_");
}
sb.append(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
sb.append("_");
sb.append(org.springframework.util.ClassUtils.getShortName(getClass()));
sb.append(".json");
return sb.toString();
}
/**
* Apply measurement options to {@link ChainedOptionsBuilder}.
*
* @param optionsBuilder must not be {@literal null}.
* @return {@link ChainedOptionsBuilder} with options applied.
* @see #getMeasurementIterations()
* @see #getMeasurementTime()
*/
private ChainedOptionsBuilder measure(ChainedOptionsBuilder optionsBuilder) {
int measurementIterations = getMeasurementIterations();
long measurementTime = getMeasurementTime();
if (measurementIterations > 0) {
optionsBuilder = optionsBuilder.measurementIterations(measurementIterations);
}
if (measurementTime > 0) {
optionsBuilder = optionsBuilder.measurementTime(TimeValue.seconds(measurementTime));
}
return optionsBuilder;
}
/**
* Apply warmup options to {@link ChainedOptionsBuilder}.
*
* @param optionsBuilder must not be {@literal null}.
* @return {@link ChainedOptionsBuilder} with options applied.
* @see #getWarmupIterations()
* @see #getWarmupTime()
*/
private ChainedOptionsBuilder warmup(ChainedOptionsBuilder optionsBuilder) {
int warmupIterations = getWarmupIterations();
long warmupTime = getWarmupTime();
if (warmupIterations > 0) {
optionsBuilder = optionsBuilder.warmupIterations(warmupIterations);
}
if (warmupTime > 0) {
optionsBuilder = optionsBuilder.warmupTime(TimeValue.seconds(warmupTime));
}
return optionsBuilder;
}
/**
* Apply forks option to {@link ChainedOptionsBuilder}.
*
* @param optionsBuilder must not be {@literal null}.
* @return {@link ChainedOptionsBuilder} with options applied.
* @see #getForksCount()
*/
private ChainedOptionsBuilder forks(ChainedOptionsBuilder optionsBuilder) {
int forks = getForksCount();
if (forks <= 0) {
return optionsBuilder;
}
return optionsBuilder.forks(forks);
}
/**
* Apply report option to {@link ChainedOptionsBuilder}.
*
* @param optionsBuilder must not be {@literal null}.
* @return {@link ChainedOptionsBuilder} with options applied.
* @throws IOException if report file cannot be created.
* @see #getReportDirectory()
*/
private ChainedOptionsBuilder report(ChainedOptionsBuilder optionsBuilder) throws IOException {
String reportDir = getReportDirectory();
if (!StringUtils.hasText(reportDir)) {
return optionsBuilder;
}
String reportFilePath = reportDir + (reportDir.endsWith(File.separator) ? "" : File.separator) + reportFilename();
File file = ResourceUtils.getFile(reportFilePath);
if (file.exists()) {
file.delete();
} else {
file.getParentFile().mkdirs();
file.createNewFile();
}
optionsBuilder.resultFormat(ResultFormatType.JSON);
optionsBuilder.result(reportFilePath);
return optionsBuilder;
}
/**
* Publish results to an external system.
*
* @param results must not be {@literal null}.
*/
private void publishResults(Collection<RunResult> results) {
if (CollectionUtils.isEmpty(results) || !environment.containsProperty("publishTo")) {
return;
}
String uri = environment.getProperty("publishTo");
try {
Utils.forUri(uri).write(results);
} catch (Exception e) {
System.err.println(String.format("Cannot save benchmark results to '%s'. Error was %s.", uri, e));
}
}
}

View File

@@ -0,0 +1,86 @@
/*
* Copyright 2017-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.microbenchmark;
import lombok.SneakyThrows;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.util.Collection;
import org.openjdk.jmh.results.RunResult;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.util.CollectionUtils;
/**
* {@link ResultsWriter} implementation of {@link URLConnection}.
*
* @since 2.0
*/
class HttpResultsWriter implements ResultsWriter {
private final String url;
HttpResultsWriter(String url) {
this.url = url;
}
@Override
@SneakyThrows
public void write(Collection<RunResult> results) {
if (CollectionUtils.isEmpty(results)) {
return;
}
StandardEnvironment env = new StandardEnvironment();
String projectVersion = env.getProperty("project.version", "unknown");
String gitBranch = env.getProperty("git.branch", "unknown");
String gitDirty = env.getProperty("git.dirty", "no");
String gitCommitId = env.getProperty("git.commit.id", "unknown");
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.setConnectTimeout(1000);
connection.setReadTimeout(1000);
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
connection.addRequestProperty("X-Project-Version", projectVersion);
connection.addRequestProperty("X-Git-Branch", gitBranch);
connection.addRequestProperty("X-Git-Dirty", gitDirty);
connection.addRequestProperty("X-Git-Commit-Id", gitCommitId);
OutputStream output = null;
try {
output = connection.getOutputStream();
output.write(ResultsWriter.Utils.jsonifyResults(results).getBytes(Charset.forName("UTF-8")));
} finally {
if (output != null) {
output.close();
}
}
if (connection.getResponseCode() >= 400) {
throw new IllegalStateException(
String.format("Status %d %s", connection.getResponseCode(), connection.getResponseMessage()));
}
}
}

View File

@@ -0,0 +1,135 @@
/*
* Copyright 2017-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.microbenchmark;
import java.net.UnknownHostException;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import org.openjdk.jmh.results.RunResult;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientURI;
import com.mongodb.util.JSON;
/**
* MongoDB specific {@link ResultsWriter} implementation.
*
* @author Christoph Strobl
* @since 2.0
*/
class MongoResultsWriter implements ResultsWriter {
private final String uri;
MongoResultsWriter(String uri) {
this.uri = uri;
}
@Override
public void write(Collection<RunResult> results) {
Date now = new Date();
StandardEnvironment env = new StandardEnvironment();
String projectVersion = env.getProperty("project.version", "unknown");
String gitBranch = env.getProperty("git.branch", "unknown");
String gitDirty = env.getProperty("git.dirty", "no");
String gitCommitId = env.getProperty("git.commit.id", "unknown");
MongoClientURI uri = new MongoClientURI(this.uri);
MongoClient client = null;
try {
client = new MongoClient(uri);
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
String dbName = StringUtils.hasText(uri.getDatabase()) ? uri.getDatabase() : "spring-data-mongodb-benchmarks";
DB db = client.getDB(dbName);
for (BasicDBObject dbo : (List<BasicDBObject>) JSON.parse(Utils.jsonifyResults(results))) {
String collectionName = extractClass(dbo.get("benchmark").toString());
BasicDBObject sink = new BasicDBObject();
sink.append("_version", projectVersion);
sink.append("_branch", gitBranch);
sink.append("_commit", gitCommitId);
sink.append("_dirty", gitDirty);
sink.append("_method", extractBenchmarkName(dbo.get("benchmark").toString()));
sink.append("_date", now);
sink.append("_snapshot", projectVersion.toLowerCase().contains("snapshot"));
sink.putAll(dbo.toMap());
db.getCollection(collectionName).insert(fixDocumentKeys(sink));
}
client.close();
}
/**
* Replace {@code .} by {@code ,}.
*
* @param doc
* @return
*/
private BasicDBObject fixDocumentKeys(BasicDBObject doc) {
BasicDBObject sanitized = new BasicDBObject();
for (Object key : doc.keySet()) {
Object value = doc.get(key);
if (value instanceof BasicDBObject) {
value = fixDocumentKeys((BasicDBObject) value);
}
if (key instanceof String) {
String newKey = (String) key;
if (newKey.contains(".")) {
newKey = newKey.replace('.', ',');
}
sanitized.put(newKey, value);
} else {
sanitized.put(ObjectUtils.nullSafeToString(key).replace('.', ','), value);
}
}
return sanitized;
}
private static String extractClass(String source) {
String tmp = source.substring(0, source.lastIndexOf('.'));
return tmp.substring(tmp.lastIndexOf(".") + 1);
}
private static String extractBenchmarkName(String source) {
return source.substring(source.lastIndexOf(".") + 1);
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright 2017-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.microbenchmark;
import lombok.SneakyThrows;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.nio.charset.Charset;
import java.util.Collection;
import org.openjdk.jmh.results.RunResult;
import org.openjdk.jmh.results.format.ResultFormatFactory;
import org.openjdk.jmh.results.format.ResultFormatType;
/**
* @author Christoph Strobl
* @since 2.0
*/
interface ResultsWriter {
/**
* Write the {@link RunResult}s.
*
* @param results can be {@literal null}.
*/
void write(Collection<RunResult> results);
/* non Java8 hack */
class Utils {
/**
* Get the uri specific {@link ResultsWriter}.
*
* @param uri must not be {@literal null}.
* @return
*/
static ResultsWriter forUri(String uri) {
return uri.startsWith("mongodb:") ? new MongoResultsWriter(uri) : new HttpResultsWriter(uri);
}
/**
* Convert {@link RunResult}s to JMH Json representation.
*
* @param results
* @return json string representation of results.
* @see org.openjdk.jmh.results.format.JSONResultFormat
*/
@SneakyThrows
static String jsonifyResults(Collection<RunResult> results) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ResultFormatFactory.getInstance(ResultFormatType.JSON, new PrintStream(baos, true, "UTF-8")).writeOut(results);
return new String(baos.toByteArray(), Charset.forName("UTF-8"));
}
}
}

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d %5p %40.40c:%4L - %m%n</pattern>
</encoder>
</appender>
<root level="error">
<appender-ref ref="console" />
</root>
</configuration>

View File

@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>1.10.0.BUILD-SNAPSHOT</version>
<version>1.10.24.BUILD-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@@ -16,6 +16,7 @@
<properties>
<jpa>2.0.0</jpa>
<hibernate>3.6.10.Final</hibernate>
<project.root>${basedir}/..</project.root>
</properties>
<dependencies>
@@ -48,7 +49,7 @@
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>1.10.0.BUILD-SNAPSHOT</version>
<version>1.10.24.BUILD-SNAPSHOT</version>
</dependency>
<dependency>

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2011 the original author or authors.
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,

View File

@@ -1,197 +1,197 @@
/*
* Copyright 2011-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.crossstore;
import javax.persistence.EntityManagerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.data.crossstore.ChangeSet;
import org.springframework.data.crossstore.ChangeSetBacked;
import org.springframework.data.crossstore.ChangeSetPersister;
import org.springframework.data.mongodb.core.CollectionCallback;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.util.ClassUtils;
import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.MongoException;
/**
* @author Thomas Risberg
* @author Oliver Gierke
* @author Alex Vengrovsk
* @author Mark Paluch
*/
public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
private static final String ENTITY_CLASS = "_entity_class";
private static final String ENTITY_ID = "_entity_id";
private static final String ENTITY_FIELD_NAME = "_entity_field_name";
private static final String ENTITY_FIELD_CLASS = "_entity_field_class";
private final Logger log = LoggerFactory.getLogger(getClass());
private MongoTemplate mongoTemplate;
private EntityManagerFactory entityManagerFactory;
public void setMongoTemplate(MongoTemplate mongoTemplate) {
this.mongoTemplate = mongoTemplate;
}
public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) {
this.entityManagerFactory = entityManagerFactory;
}
/*
* (non-Javadoc)
* @see org.springframework.data.crossstore.ChangeSetPersister#getPersistentState(java.lang.Class, java.lang.Object, org.springframework.data.crossstore.ChangeSet)
*/
public void getPersistentState(Class<? extends ChangeSetBacked> entityClass, Object id, final ChangeSet changeSet)
throws DataAccessException, NotFoundException {
if (id == null) {
log.debug("Unable to load MongoDB data for null id");
return;
}
String collName = getCollectionNameForEntity(entityClass);
final DBObject dbk = new BasicDBObject();
dbk.put(ENTITY_ID, id);
dbk.put(ENTITY_CLASS, entityClass.getName());
if (log.isDebugEnabled()) {
log.debug("Loading MongoDB data for {}", dbk);
}
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
for (DBObject dbo : collection.find(dbk)) {
String key = (String) dbo.get(ENTITY_FIELD_NAME);
if (log.isDebugEnabled()) {
log.debug("Processing key: {}", key);
}
if (!changeSet.getValues().containsKey(key)) {
String className = (String) dbo.get(ENTITY_FIELD_CLASS);
if (className == null) {
throw new DataIntegrityViolationException(
"Unble to convert property " + key + ": Invalid metadata, " + ENTITY_FIELD_CLASS + " not available");
}
Class<?> clazz = ClassUtils.resolveClassName(className, ClassUtils.getDefaultClassLoader());
Object value = mongoTemplate.getConverter().read(clazz, dbo);
if (log.isDebugEnabled()) {
log.debug("Adding to ChangeSet: {}", key);
}
changeSet.set(key, value);
}
}
return null;
}
});
}
/*
* (non-Javadoc)
* @see org.springframework.data.crossstore.ChangeSetPersister#getPersistentId(org.springframework.data.crossstore.ChangeSetBacked, org.springframework.data.crossstore.ChangeSet)
*/
public Object getPersistentId(ChangeSetBacked entity, ChangeSet cs) throws DataAccessException {
if (log.isDebugEnabled()) {
log.debug("getPersistentId called on {}", entity);
}
if (entityManagerFactory == null) {
throw new DataAccessResourceFailureException("EntityManagerFactory cannot be null");
}
return entityManagerFactory.getPersistenceUnitUtil().getIdentifier(entity);
}
/*
* (non-Javadoc)
* @see org.springframework.data.crossstore.ChangeSetPersister#persistState(org.springframework.data.crossstore.ChangeSetBacked, org.springframework.data.crossstore.ChangeSet)
*/
public Object persistState(ChangeSetBacked entity, ChangeSet cs) throws DataAccessException {
if (cs == null) {
log.debug("Flush: changeset was null, nothing to flush.");
return 0L;
}
if (log.isDebugEnabled()) {
log.debug("Flush: changeset: {}", cs.getValues());
}
String collName = getCollectionNameForEntity(entity.getClass());
if (mongoTemplate.getCollection(collName) == null) {
mongoTemplate.createCollection(collName);
}
for (String key : cs.getValues().keySet()) {
if (key != null && !key.startsWith("_") && !key.equals(ChangeSetPersister.ID_KEY)) {
Object value = cs.getValues().get(key);
final DBObject dbQuery = new BasicDBObject();
dbQuery.put(ENTITY_ID, getPersistentId(entity, cs));
dbQuery.put(ENTITY_CLASS, entity.getClass().getName());
dbQuery.put(ENTITY_FIELD_NAME, key);
DBObject dbId = mongoTemplate.execute(collName, new CollectionCallback<DBObject>() {
public DBObject doInCollection(DBCollection collection) throws MongoException, DataAccessException {
return collection.findOne(dbQuery);
}
});
if (value == null) {
if (log.isDebugEnabled()) {
log.debug("Flush: removing: {}", dbQuery);
}
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
collection.remove(dbQuery);
return null;
}
});
} else {
final DBObject dbDoc = new BasicDBObject();
dbDoc.putAll(dbQuery);
if (log.isDebugEnabled()) {
log.debug("Flush: saving: {}", dbQuery);
}
mongoTemplate.getConverter().write(value, dbDoc);
dbDoc.put(ENTITY_FIELD_CLASS, value.getClass().getName());
if (dbId != null) {
dbDoc.put("_id", dbId.get("_id"));
}
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
collection.save(dbDoc);
return null;
}
});
}
}
}
return 0L;
}
/**
* Returns the collection the given entity type shall be persisted to.
*
* @param entityClass must not be {@literal null}.
* @return
*/
private String getCollectionNameForEntity(Class<? extends ChangeSetBacked> entityClass) {
return mongoTemplate.getCollectionName(entityClass);
}
}
/*
* 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.crossstore;
import javax.persistence.EntityManagerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.data.crossstore.ChangeSet;
import org.springframework.data.crossstore.ChangeSetBacked;
import org.springframework.data.crossstore.ChangeSetPersister;
import org.springframework.data.mongodb.core.CollectionCallback;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.util.ClassUtils;
import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.MongoException;
/**
* @author Thomas Risberg
* @author Oliver Gierke
* @author Alex Vengrovsk
* @author Mark Paluch
*/
public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
private static final String ENTITY_CLASS = "_entity_class";
private static final String ENTITY_ID = "_entity_id";
private static final String ENTITY_FIELD_NAME = "_entity_field_name";
private static final String ENTITY_FIELD_CLASS = "_entity_field_class";
private final Logger log = LoggerFactory.getLogger(getClass());
private MongoTemplate mongoTemplate;
private EntityManagerFactory entityManagerFactory;
public void setMongoTemplate(MongoTemplate mongoTemplate) {
this.mongoTemplate = mongoTemplate;
}
public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) {
this.entityManagerFactory = entityManagerFactory;
}
/*
* (non-Javadoc)
* @see org.springframework.data.crossstore.ChangeSetPersister#getPersistentState(java.lang.Class, java.lang.Object, org.springframework.data.crossstore.ChangeSet)
*/
public void getPersistentState(Class<? extends ChangeSetBacked> entityClass, Object id, final ChangeSet changeSet)
throws DataAccessException, NotFoundException {
if (id == null) {
log.debug("Unable to load MongoDB data for null id");
return;
}
String collName = getCollectionNameForEntity(entityClass);
final DBObject dbk = new BasicDBObject();
dbk.put(ENTITY_ID, id);
dbk.put(ENTITY_CLASS, entityClass.getName());
if (log.isDebugEnabled()) {
log.debug("Loading MongoDB data for {}", dbk);
}
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
for (DBObject dbo : collection.find(dbk)) {
String key = (String) dbo.get(ENTITY_FIELD_NAME);
if (log.isDebugEnabled()) {
log.debug("Processing key: {}", key);
}
if (!changeSet.getValues().containsKey(key)) {
String className = (String) dbo.get(ENTITY_FIELD_CLASS);
if (className == null) {
throw new DataIntegrityViolationException(
"Unble to convert property " + key + ": Invalid metadata, " + ENTITY_FIELD_CLASS + " not available");
}
Class<?> clazz = ClassUtils.resolveClassName(className, ClassUtils.getDefaultClassLoader());
Object value = mongoTemplate.getConverter().read(clazz, dbo);
if (log.isDebugEnabled()) {
log.debug("Adding to ChangeSet: {}", key);
}
changeSet.set(key, value);
}
}
return null;
}
});
}
/*
* (non-Javadoc)
* @see org.springframework.data.crossstore.ChangeSetPersister#getPersistentId(org.springframework.data.crossstore.ChangeSetBacked, org.springframework.data.crossstore.ChangeSet)
*/
public Object getPersistentId(ChangeSetBacked entity, ChangeSet cs) throws DataAccessException {
if (log.isDebugEnabled()) {
log.debug("getPersistentId called on {}", entity);
}
if (entityManagerFactory == null) {
throw new DataAccessResourceFailureException("EntityManagerFactory cannot be null");
}
return entityManagerFactory.getPersistenceUnitUtil().getIdentifier(entity);
}
/*
* (non-Javadoc)
* @see org.springframework.data.crossstore.ChangeSetPersister#persistState(org.springframework.data.crossstore.ChangeSetBacked, org.springframework.data.crossstore.ChangeSet)
*/
public Object persistState(ChangeSetBacked entity, ChangeSet cs) throws DataAccessException {
if (cs == null) {
log.debug("Flush: changeset was null, nothing to flush.");
return 0L;
}
if (log.isDebugEnabled()) {
log.debug("Flush: changeset: {}", cs.getValues());
}
String collName = getCollectionNameForEntity(entity.getClass());
if (mongoTemplate.getCollection(collName) == null) {
mongoTemplate.createCollection(collName);
}
for (String key : cs.getValues().keySet()) {
if (key != null && !key.startsWith("_") && !key.equals(ChangeSetPersister.ID_KEY)) {
Object value = cs.getValues().get(key);
final DBObject dbQuery = new BasicDBObject();
dbQuery.put(ENTITY_ID, getPersistentId(entity, cs));
dbQuery.put(ENTITY_CLASS, entity.getClass().getName());
dbQuery.put(ENTITY_FIELD_NAME, key);
DBObject dbId = mongoTemplate.execute(collName, new CollectionCallback<DBObject>() {
public DBObject doInCollection(DBCollection collection) throws MongoException, DataAccessException {
return collection.findOne(dbQuery);
}
});
if (value == null) {
if (log.isDebugEnabled()) {
log.debug("Flush: removing: {}", dbQuery);
}
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
collection.remove(dbQuery);
return null;
}
});
} else {
final DBObject dbDoc = new BasicDBObject();
dbDoc.putAll(dbQuery);
if (log.isDebugEnabled()) {
log.debug("Flush: saving: {}", dbQuery);
}
mongoTemplate.getConverter().write(value, dbDoc);
dbDoc.put(ENTITY_FIELD_CLASS, value.getClass().getName());
if (dbId != null) {
dbDoc.put("_id", dbId.get("_id"));
}
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
collection.save(dbDoc);
return null;
}
});
}
}
}
return 0L;
}
/**
* Returns the collection the given entity type shall be persisted to.
*
* @param entityClass must not be {@literal null}.
* @return
*/
private String getCollectionNameForEntity(Class<? extends ChangeSetBacked> entityClass) {
return mongoTemplate.getCollectionName(entityClass);
}
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2011 the original author or authors.
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2011 the original author or authors.
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2011-2013 the original author or authors.
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2011 the original author or authors.
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2011 the original author or authors.
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2011 the original author or authors.
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
@@ -13,7 +13,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>1.10.0.BUILD-SNAPSHOT</version>
<version>1.10.24.BUILD-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@@ -28,10 +28,6 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>wagon-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>1.10.0.BUILD-SNAPSHOT</version>
<version>1.10.24.BUILD-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@@ -14,6 +14,7 @@
<properties>
<log4j>1.2.16</log4j>
<project.root>${basedir}/..</project.root>
</properties>
<dependencies>

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2011-2016 the original author or authors.
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -18,6 +18,8 @@ package org.springframework.data.mongodb.log4j;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.apache.log4j.AppenderSkeleton;
@@ -31,14 +33,17 @@ import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.Mongo;
import com.mongodb.MongoClient;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.WriteConcern;
/**
* Log4j appender writing log entries into a MongoDB instance.
*
*
* @author Jon Brisbin
* @author Oliver Gierke
* @auhtor Christoph Strobl
* @author Christoph Strobl
* @author Ricardo Espirito Santo
*/
public class MongoLog4jAppender extends AppenderSkeleton {
@@ -56,6 +61,9 @@ public class MongoLog4jAppender extends AppenderSkeleton {
protected String host = "localhost";
protected int port = 27017;
protected String username;
protected String password;
protected String authenticationDatabase;
protected String database = "logs";
protected String collectionPattern = "%c";
protected PatternLayout collectionLayout = new PatternLayout(collectionPattern);
@@ -65,8 +73,7 @@ public class MongoLog4jAppender extends AppenderSkeleton {
protected Mongo mongo;
protected DB db;
public MongoLog4jAppender() {
}
public MongoLog4jAppender() {}
public MongoLog4jAppender(boolean isActive) {
super(isActive);
@@ -88,6 +95,53 @@ public class MongoLog4jAppender extends AppenderSkeleton {
this.port = port;
}
/**
* @return
* @since 1.10
*/
public String getUsername() {
return username;
}
/**
* @param username may be {@literal null} for unauthenticated access.
* @since 1.10
*/
public void setUsername(String username) {
this.username = username;
}
/**
* @return
* @since 1.10
*/
public String getPassword() {
return password;
}
/**
* @param password may be {@literal null} for unauthenticated access.
* @since 1.10
*/
public void setPassword(String password) {
this.password = password;
}
/**
* @return
*/
public String getAuthenticationDatabase() {
return authenticationDatabase;
}
/**
* @param authenticationDatabase may be {@literal null} to use {@link #getDatabase()} as authentication database.
* @since 1.10
*/
public void setAuthenticationDatabase(String authenticationDatabase) {
this.authenticationDatabase = authenticationDatabase;
}
public String getDatabase() {
return database;
}
@@ -113,14 +167,14 @@ public class MongoLog4jAppender extends AppenderSkeleton {
this.applicationId = applicationId;
}
public void setWarnOrHigherWriteConcern(String wc) {
this.warnOrHigherWriteConcern = WriteConcern.valueOf(wc);
}
public String getWarnOrHigherWriteConcern() {
return warnOrHigherWriteConcern.toString();
}
public void setWarnOrHigherWriteConcern(String wc) {
this.warnOrHigherWriteConcern = WriteConcern.valueOf(wc);
}
public String getInfoOrLowerWriteConcern() {
return infoOrLowerWriteConcern.toString();
}
@@ -130,10 +184,26 @@ public class MongoLog4jAppender extends AppenderSkeleton {
}
protected void connectToMongo() throws UnknownHostException {
this.mongo = new MongoClient(host, port);
this.mongo = createMongoClient();
this.db = mongo.getDB(database);
}
private MongoClient createMongoClient() throws UnknownHostException {
ServerAddress serverAddress = new ServerAddress(host, port);
if (null == password || null == username) {
return new MongoClient(serverAddress);
}
String authenticationDatabaseToUse = authenticationDatabase == null ? this.database : authenticationDatabase;
MongoCredential mongoCredential = MongoCredential.createCredential(username,
authenticationDatabaseToUse, password.toCharArray());
List<MongoCredential> credentials = Collections.singletonList(mongoCredential);
return new MongoClient(serverAddress, credentials);
}
/*
* (non-Javadoc)
* @see org.apache.log4j.AppenderSkeleton#append(org.apache.log4j.spi.LoggingEvent)

View File

@@ -0,0 +1,114 @@
/*
* Copyright 2016-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.log4j;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.util.Calendar;
import java.util.Collections;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.log4j.MDC;
import org.apache.log4j.PropertyConfigurator;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.BasicDBObjectBuilder;
import com.mongodb.DB;
import com.mongodb.DBCursor;
import com.mongodb.MongoClient;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
/**
* Integration tests for {@link MongoLog4jAppender} using authentication.
*
* @author Mark Paluch
*/
public class MongoLog4jAppenderAuthenticationIntegrationTests {
private final static String username = "admin";
private final static String password = "test";
private final static String authenticationDatabase = "logs";
MongoClient mongo;
DB db;
String collection;
ServerAddress serverLocation;
Logger log;
@Before
public void setUp() throws Exception {
serverLocation = new ServerAddress("localhost", 27017);
mongo = new MongoClient(serverLocation);
db = mongo.getDB("logs");
BasicDBList roles = new BasicDBList();
roles.add("dbOwner");
db.command(new BasicDBObjectBuilder().add("createUser", username).add("pwd", password).add("roles", roles).get());
mongo.close();
mongo = new MongoClient(serverLocation, Collections
.singletonList(MongoCredential.createCredential(username, authenticationDatabase, password.toCharArray())));
db = mongo.getDB("logs");
Calendar now = Calendar.getInstance();
collection = String.valueOf(now.get(Calendar.YEAR)) + String.format("%1$02d", now.get(Calendar.MONTH) + 1);
LogManager.resetConfiguration();
PropertyConfigurator.configure(getClass().getResource("/log4j-with-authentication.properties"));
log = Logger.getLogger(MongoLog4jAppenderIntegrationTests.class.getName());
}
@After
public void tearDown() {
if (db != null) {
db.getCollection(collection).remove(new BasicDBObject());
db.command(new BasicDBObject("dropUser", username));
}
LogManager.resetConfiguration();
PropertyConfigurator.configure(getClass().getResource("/log4j.properties"));
}
@Test
public void testLogging() {
log.debug("DEBUG message");
log.info("INFO message");
log.warn("WARN message");
log.error("ERROR message");
DBCursor msgs = db.getCollection(collection).find();
assertThat(msgs.count(), is(4));
}
@Test
public void testProperties() {
MDC.put("property", "one");
log.debug("DEBUG message");
}
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2011-2016 the original author or authors.
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -20,8 +20,10 @@ import static org.junit.Assert.*;
import java.util.Calendar;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.log4j.MDC;
import org.apache.log4j.PropertyConfigurator;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -30,31 +32,34 @@ import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCursor;
import com.mongodb.MongoClient;
import com.mongodb.ServerAddress;
/**
* Integration tests for {@link MongoLog4jAppender}.
*
*
* @author Jon Brisbin
* @author Oliver Gierke
* @author Christoph Strobl
*/
public class MongoLog4jAppenderIntegrationTests {
static final String NAME = MongoLog4jAppenderIntegrationTests.class.getName();
private static final Logger log = Logger.getLogger(NAME);
MongoClient mongo;
DB db;
String collection;
ServerAddress serverLocation;
Logger log;
@Before
public void setUp() throws Exception {
serverLocation = new ServerAddress("localhost", 27017);
mongo = new MongoClient("localhost", 27017);
mongo = new MongoClient(serverLocation);
db = mongo.getDB("logs");
Calendar now = Calendar.getInstance();
collection = String.valueOf(now.get(Calendar.YEAR)) + String.format("%1$02d", now.get(Calendar.MONTH) + 1);
log = Logger.getLogger(MongoLog4jAppenderIntegrationTests.class.getName());
}
@After
@@ -76,7 +81,6 @@ public class MongoLog4jAppenderIntegrationTests {
@Test
public void testProperties() {
MDC.put("property", "one");
log.debug("DEBUG message");
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2013 the original author or authors.
* Copyright 2013-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
* 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,
@@ -24,10 +24,7 @@ import org.junit.Test;
*/
public class MongoLog4jAppenderUnitTests {
/**
* @see DATAMONGO-641
*/
@Test
@Test // DATAMONGO-641
public void closesWithoutMongoInstancePresent() {
new MongoLog4jAppender().close();
}

View File

@@ -0,0 +1,16 @@
log4j.rootCategory=INFO, mongo
log4j.appender.mongo=org.springframework.data.mongodb.log4j.MongoLog4jAppender
log4j.appender.mongo.layout=org.apache.log4j.PatternLayout
log4j.appender.mongo.layout.ConversionPattern=%d %p [%c] - <%m>%n
log4j.appender.mongo.host = localhost
log4j.appender.mongo.port = 27017
log4j.appender.mongo.database = logs
log4j.appender.mongo.username = admin
log4j.appender.mongo.password = test
log4j.appender.mongo.authenticationDatabase = logs
log4j.appender.mongo.collectionPattern = %X{year}%X{month}
log4j.appender.mongo.applicationId = my.application
log4j.appender.mongo.warnOrHigherWriteConcern = FSYNC_SAFE
log4j.category.org.springframework.data.mongodb=DEBUG

View File

@@ -1,13 +1,13 @@
log4j.rootCategory=INFO, stdout
log4j.rootCategory=INFO, mongo
log4j.appender.stdout=org.springframework.data.mongodb.log4j.MongoLog4jAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n
log4j.appender.stdout.host = localhost
log4j.appender.stdout.port = 27017
log4j.appender.stdout.database = logs
log4j.appender.stdout.collectionPattern = %X{year}%X{month}
log4j.appender.stdout.applicationId = my.application
log4j.appender.stdout.warnOrHigherWriteConcern = FSYNC_SAFE
log4j.appender.mongo=org.springframework.data.mongodb.log4j.MongoLog4jAppender
log4j.appender.mongo.layout=org.apache.log4j.PatternLayout
log4j.appender.mongo.layout.ConversionPattern=%d %p [%c] - <%m>%n
log4j.appender.mongo.host = localhost
log4j.appender.mongo.port = 27017
log4j.appender.mongo.database = logs
log4j.appender.mongo.collectionPattern = %X{year}%X{month}
log4j.appender.mongo.applicationId = my.application
log4j.appender.mongo.warnOrHigherWriteConcern = FSYNC_SAFE
log4j.category.org.springframework.data.mongodb=DEBUG

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
@@ -11,13 +11,14 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>1.10.0.BUILD-SNAPSHOT</version>
<version>1.10.24.BUILD-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<properties>
<objenesis>1.3</objenesis>
<equalsverifier>1.5</equalsverifier>
<project.root>${basedir}/..</project.root>
</properties>
<dependencies>
@@ -147,7 +148,6 @@
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson}</version>
<optional>true</optional>
</dependency>

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2015 the original author or authors.
* Copyright 2015-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
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2010-2012 the original author or authors.
* Copyright 2010-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
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2010-2011 the original author or authors.
* Copyright 2010-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
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2013 the original author or authors.
* Copyright 2013-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
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2011 the original author or authors.
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2011-2013 the original author or authors.
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -23,7 +23,7 @@ import com.mongodb.DB;
/**
* Interface for factories creating {@link DB} instances.
*
*
* @author Mark Pollack
* @author Thomas Darimont
*/
@@ -31,7 +31,7 @@ public interface MongoDbFactory {
/**
* Creates a default {@link DB} instance.
*
*
* @return
* @throws DataAccessException
*/
@@ -39,7 +39,7 @@ public interface MongoDbFactory {
/**
* Creates a {@link DB} instance to access the database with the given name.
*
*
* @param dbName must not be {@literal null} or empty.
* @return
* @throws DataAccessException
@@ -48,7 +48,7 @@ public interface MongoDbFactory {
/**
* Exposes a shared {@link MongoExceptionTranslator}.
*
*
* @return will never be {@literal null}.
*/
PersistenceExceptionTranslator getExceptionTranslator();

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2010-2011 the original author or authors.
* Copyright 2010-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
* 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,

View File

@@ -1,297 +1,297 @@
/*
* Copyright 2011-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.config;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.data.annotation.Persistent;
import org.springframework.data.authentication.UserCredentials;
import org.springframework.data.mapping.context.MappingContextIsNewStrategyFactory;
import org.springframework.data.mapping.model.CamelCaseAbbreviatingFieldNamingStrategy;
import org.springframework.data.mapping.model.FieldNamingStrategy;
import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy;
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.CustomConversions;
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.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.support.CachingIsNewStrategyFactory;
import org.springframework.data.support.IsNewStrategyFactory;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
import com.mongodb.Mongo;
import com.mongodb.MongoClient;
/**
* Base class for Spring Data MongoDB configuration using JavaConfig.
*
* @author Mark Pollack
* @author Oliver Gierke
* @author Thomas Darimont
* @author Ryan Tenney
* @author Christoph Strobl
*/
@Configuration
public abstract class AbstractMongoConfiguration {
/**
* Return the name of the database to connect to.
*
* @return must not be {@literal null}.
*/
protected abstract String getDatabaseName();
/**
* Return the name of the authentication database to use. Defaults to {@literal null} and will turn into the value
* returned by {@link #getDatabaseName()} later on effectively.
*
* @return
* @deprecated since 1.7. {@link MongoClient} should hold authentication data within
* {@link MongoClient#getCredentialsList()}
*/
@Deprecated
protected String getAuthenticationDatabaseName() {
return null;
}
/**
* Return the {@link Mongo} instance to connect to. Annotate with {@link Bean} in case you want to expose a
* {@link Mongo} instance to the {@link org.springframework.context.ApplicationContext}.
*
* @return
* @throws Exception
*/
public abstract Mongo mongo() throws Exception;
/**
* Creates a {@link MongoTemplate}.
*
* @return
* @throws Exception
*/
@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 Mongo} instance
* configured in {@link #mongo()}.
*
* @see #mongo()
* @see #mongoTemplate()
* @return
* @throws Exception
*/
@Bean
public MongoDbFactory mongoDbFactory() throws Exception {
return new SimpleMongoDbFactory(mongo(), getDatabaseName(), getUserCredentials(), getAuthenticationDatabaseName());
}
/**
* 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
protected String getMappingBasePackage() {
Package mappingBasePackage = getClass().getPackage();
return mappingBasePackage == null ? null : mappingBasePackage.getName();
}
/**
* Returns the base packages to scan for MongoDB mapped entities at startup. 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 packages to scan for mapped {@link Document} classes or an empty collection to not enable scanning
* for entities.
* @since 1.10
*/
protected Collection<String> getMappingBasePackages() {
return Collections.singleton(getMappingBasePackage());
}
/**
* Return {@link UserCredentials} to be used when connecting to the MongoDB instance or {@literal null} if none shall
* be used.
*
* @return
* @deprecated since 1.7. {@link MongoClient} should hold authentication data within
* {@link MongoClient#getCredentialsList()}
*/
@Deprecated
protected UserCredentials getUserCredentials() {
return null;
}
/**
* Creates a {@link MongoMappingContext} equipped with entity classes scanned from the mapping base package.
*
* @see #getMappingBasePackage()
* @return
* @throws ClassNotFoundException
*/
@Bean
public MongoMappingContext mongoMappingContext() throws ClassNotFoundException {
MongoMappingContext mappingContext = new MongoMappingContext();
mappingContext.setInitialEntitySet(getInitialEntitySet());
mappingContext.setSimpleTypeHolder(customConversions().getSimpleTypeHolder());
mappingContext.setFieldNamingStrategy(fieldNamingStrategy());
return mappingContext;
}
/**
* Returns a {@link MappingContextIsNewStrategyFactory} wrapped into a {@link CachingIsNewStrategyFactory}.
*
* @return
* @throws ClassNotFoundException
*/
@Bean
public IsNewStrategyFactory isNewStrategyFactory() throws ClassNotFoundException {
return new CachingIsNewStrategyFactory(new MappingContextIsNewStrategyFactory(mongoMappingContext()));
}
/**
* 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 CustomConversions} instance by default.
*
* @return must not be {@literal null}.
*/
@Bean
public CustomConversions customConversions() {
return new CustomConversions(Collections.emptyList());
}
/**
* 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());
return converter;
}
/**
* Scans the mapping base package for classes annotated with {@link Document}. By default, it scans for entities in
* all packages returned by {@link #getMappingBasePackages()}.
*
* @see #getMappingBasePackages()
* @return
* @throws ClassNotFoundException
*/
protected Set<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
Set<Class<?>> initialEntitySet = new HashSet<Class<?>>();
for (String basePackage : getMappingBasePackages()) {
initialEntitySet.addAll(scanForEntities(basePackage));
}
return initialEntitySet;
}
/**
* Scans the given base package for entities, i.e. MongoDB specific types annotated with {@link Document} and
* {@link Persistent}.
*
* @param basePackage must not be {@literal null}.
* @return
* @throws ClassNotFoundException
* @since 1.10
*/
protected Set<Class<?>> scanForEntities(String basePackage) throws ClassNotFoundException {
if (!StringUtils.hasText(basePackage)) {
return Collections.emptySet();
}
Set<Class<?>> initialEntitySet = new HashSet<Class<?>>();
if (StringUtils.hasText(basePackage)) {
ClassPathScanningCandidateComponentProvider componentProvider = new ClassPathScanningCandidateComponentProvider(
false);
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Document.class));
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Persistent.class));
for (BeanDefinition candidate : componentProvider.findCandidateComponents(basePackage)) {
initialEntitySet
.add(ClassUtils.forName(candidate.getBeanClassName(), AbstractMongoConfiguration.class.getClassLoader()));
}
}
return initialEntitySet;
}
/**
* 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()}.
*
* @return
*/
protected boolean abbreviateFieldNames() {
return false;
}
/**
* Configures a {@link FieldNamingStrategy} on the {@link MongoMappingContext} instance created.
*
* @return
* @since 1.5
*/
protected FieldNamingStrategy fieldNamingStrategy() {
return abbreviateFieldNames() ? new CamelCaseAbbreviatingFieldNamingStrategy()
: PropertyNameFieldNamingStrategy.INSTANCE;
}
}
/*
* 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.config;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.data.annotation.Persistent;
import org.springframework.data.authentication.UserCredentials;
import org.springframework.data.mapping.context.MappingContextIsNewStrategyFactory;
import org.springframework.data.mapping.model.CamelCaseAbbreviatingFieldNamingStrategy;
import org.springframework.data.mapping.model.FieldNamingStrategy;
import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy;
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.CustomConversions;
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.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.support.CachingIsNewStrategyFactory;
import org.springframework.data.support.IsNewStrategyFactory;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
import com.mongodb.Mongo;
import com.mongodb.MongoClient;
/**
* Base class for Spring Data MongoDB configuration using JavaConfig.
*
* @author Mark Pollack
* @author Oliver Gierke
* @author Thomas Darimont
* @author Ryan Tenney
* @author Christoph Strobl
*/
@Configuration
public abstract class AbstractMongoConfiguration {
/**
* Return the name of the database to connect to.
*
* @return must not be {@literal null}.
*/
protected abstract String getDatabaseName();
/**
* Return the name of the authentication database to use. Defaults to {@literal null} and will turn into the value
* returned by {@link #getDatabaseName()} later on effectively.
*
* @return
* @deprecated since 1.7. {@link MongoClient} should hold authentication data within
* {@link MongoClient#getCredentialsList()}
*/
@Deprecated
protected String getAuthenticationDatabaseName() {
return null;
}
/**
* Return the {@link Mongo} instance to connect to. Annotate with {@link Bean} in case you want to expose a
* {@link Mongo} instance to the {@link org.springframework.context.ApplicationContext}.
*
* @return
* @throws Exception
*/
public abstract Mongo mongo() throws Exception;
/**
* Creates a {@link MongoTemplate}.
*
* @return
* @throws Exception
*/
@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 Mongo} instance
* configured in {@link #mongo()}.
*
* @see #mongo()
* @see #mongoTemplate()
* @return
* @throws Exception
*/
@Bean
public MongoDbFactory mongoDbFactory() throws Exception {
return new SimpleMongoDbFactory(mongo(), getDatabaseName(), getUserCredentials(), getAuthenticationDatabaseName());
}
/**
* 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
protected String getMappingBasePackage() {
Package mappingBasePackage = getClass().getPackage();
return mappingBasePackage == null ? null : mappingBasePackage.getName();
}
/**
* Returns the base packages to scan for MongoDB mapped entities at startup. 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 packages to scan for mapped {@link Document} classes or an empty collection to not enable scanning
* for entities.
* @since 1.10
*/
protected Collection<String> getMappingBasePackages() {
return Collections.singleton(getMappingBasePackage());
}
/**
* Return {@link UserCredentials} to be used when connecting to the MongoDB instance or {@literal null} if none shall
* be used.
*
* @return
* @deprecated since 1.7. {@link MongoClient} should hold authentication data within
* {@link MongoClient#getCredentialsList()}
*/
@Deprecated
protected UserCredentials getUserCredentials() {
return null;
}
/**
* Creates a {@link MongoMappingContext} equipped with entity classes scanned from the mapping base package.
*
* @see #getMappingBasePackage()
* @return
* @throws ClassNotFoundException
*/
@Bean
public MongoMappingContext mongoMappingContext() throws ClassNotFoundException {
MongoMappingContext mappingContext = new MongoMappingContext();
mappingContext.setInitialEntitySet(getInitialEntitySet());
mappingContext.setSimpleTypeHolder(customConversions().getSimpleTypeHolder());
mappingContext.setFieldNamingStrategy(fieldNamingStrategy());
return mappingContext;
}
/**
* Returns a {@link MappingContextIsNewStrategyFactory} wrapped into a {@link CachingIsNewStrategyFactory}.
*
* @return
* @throws ClassNotFoundException
*/
@Bean
public IsNewStrategyFactory isNewStrategyFactory() throws ClassNotFoundException {
return new CachingIsNewStrategyFactory(new MappingContextIsNewStrategyFactory(mongoMappingContext()));
}
/**
* 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 CustomConversions} instance by default.
*
* @return must not be {@literal null}.
*/
@Bean
public CustomConversions customConversions() {
return new CustomConversions(Collections.emptyList());
}
/**
* 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());
return converter;
}
/**
* Scans the mapping base package for classes annotated with {@link Document}. By default, it scans for entities in
* all packages returned by {@link #getMappingBasePackages()}.
*
* @see #getMappingBasePackages()
* @return
* @throws ClassNotFoundException
*/
protected Set<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
Set<Class<?>> initialEntitySet = new HashSet<Class<?>>();
for (String basePackage : getMappingBasePackages()) {
initialEntitySet.addAll(scanForEntities(basePackage));
}
return initialEntitySet;
}
/**
* Scans the given base package for entities, i.e. MongoDB specific types annotated with {@link Document} and
* {@link Persistent}.
*
* @param basePackage must not be {@literal null}.
* @return
* @throws ClassNotFoundException
* @since 1.10
*/
protected Set<Class<?>> scanForEntities(String basePackage) throws ClassNotFoundException {
if (!StringUtils.hasText(basePackage)) {
return Collections.emptySet();
}
Set<Class<?>> initialEntitySet = new HashSet<Class<?>>();
if (StringUtils.hasText(basePackage)) {
ClassPathScanningCandidateComponentProvider componentProvider = new ClassPathScanningCandidateComponentProvider(
false);
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Document.class));
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Persistent.class));
for (BeanDefinition candidate : componentProvider.findCandidateComponents(basePackage)) {
initialEntitySet
.add(ClassUtils.forName(candidate.getBeanClassName(), AbstractMongoConfiguration.class.getClassLoader()));
}
}
return initialEntitySet;
}
/**
* 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()}.
*
* @return
*/
protected boolean abbreviateFieldNames() {
return false;
}
/**
* Configures a {@link FieldNamingStrategy} on the {@link MongoMappingContext} instance created.
*
* @return
* @since 1.5
*/
protected FieldNamingStrategy fieldNamingStrategy() {
return abbreviateFieldNames() ? new CamelCaseAbbreviatingFieldNamingStrategy()
: PropertyNameFieldNamingStrategy.INSTANCE;
}
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2011-2014 the original author or authors.
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2013 the original author or authors.
* Copyright 2013-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
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2013-2014 the original author or authors.
* Copyright 2013-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
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2011-2014 the original author or authors.
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -361,7 +361,9 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
* @param filters
*/
public NegatingFilter(TypeFilter... filters) {
Assert.notNull(filters);
Assert.notNull(filters, "TypeFilters must not be null");
this.delegates = new HashSet<TypeFilter>(Arrays.asList(filters));
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2012-2014 the original author or authors.
* Copyright 2012-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
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2013-2016 the original author or authors.
* Copyright 2013-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
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2015 the original author or authors.
* Copyright 2015-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
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2015 the original author or authors.
* Copyright 2015-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
* 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,
@@ -16,6 +16,7 @@
package org.springframework.data.mongodb.config;
import java.beans.PropertyEditorSupport;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -23,15 +24,18 @@ import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
import com.mongodb.MongoCredential;
/**
* Parse a {@link String} to a Collection of {@link MongoCredential}.
*
*
* @author Christoph Strobl
* @author Oliver Gierke
* @author Stephen Tyler Conrad
* @author Mark Paluch
* @since 1.7
*/
public class MongoCredentialPropertyEditor extends PropertyEditorSupport {
@@ -95,6 +99,20 @@ public class MongoCredentialPropertyEditor extends PropertyEditorSupport {
verifyDatabasePresent(database);
credentials.add(MongoCredential.createScramSha1Credential(userNameAndPassword[0], database,
userNameAndPassword[1].toCharArray()));
} else if ("SCRAM-SHA-256".equals(authMechanism)) {
Method createScramSha256Credential = ReflectionUtils.findMethod(MongoCredential.class,
"createScramSha256Credential", String.class, String.class, char[].class);
if (createScramSha256Credential == null) {
throw new IllegalArgumentException(
"SCRAM-SHA-256 auth mechanism is available as of MongoDB 4 and MongoDB Java Driver 3.8! Please make sure to use at least those versions.");
}
verifyUsernameAndPasswordPresent(userNameAndPassword);
verifyDatabasePresent(database);
credentials.add(MongoCredential.class.cast(ReflectionUtils.invokeMethod(createScramSha256Credential, null,
userNameAndPassword[0], database, userNameAndPassword[1].toCharArray())));
} else {
throw new IllegalArgumentException(
String.format("Cannot create MongoCredentials for unknown auth mechanism '%s'!", authMechanism));
@@ -156,7 +174,7 @@ public class MongoCredentialPropertyEditor extends PropertyEditorSupport {
private static Properties extractOptions(String text) {
int optionsSeperationIndex = text.lastIndexOf(OPTIONS_DELIMINATOR);
int dbSeperationIndex = text.lastIndexOf(OPTIONS_DELIMINATOR);
int dbSeperationIndex = text.lastIndexOf(DATABASE_DELIMINATOR);
if (optionsSeperationIndex == -1 || dbSeperationIndex > optionsSeperationIndex) {
return new Properties();
@@ -166,6 +184,11 @@ public class MongoCredentialPropertyEditor extends PropertyEditorSupport {
for (String option : text.substring(optionsSeperationIndex + 1).split(OPTION_VALUE_DELIMINATOR)) {
String[] optionArgs = option.split("=");
if (optionArgs.length == 1) {
throw new IllegalArgumentException(String.format("Query parameter '%s' has no value!", optionArgs[0]));
}
properties.put(optionArgs[0], optionArgs[1]);
}

View File

@@ -5,7 +5,7 @@
* 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
* 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,

View File

@@ -1,69 +1,69 @@
/*
* Copyright 2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.config;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.data.mongodb.core.MongoAdmin;
import org.springframework.data.mongodb.monitor.*;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
public class MongoJmxParser implements BeanDefinitionParser {
public BeanDefinition parse(Element element, ParserContext parserContext) {
String name = element.getAttribute("mongo-ref");
if (!StringUtils.hasText(name)) {
name = "mongo";
}
registerJmxComponents(name, element, parserContext);
return null;
}
protected void registerJmxComponents(String mongoRefName, Element element, ParserContext parserContext) {
Object eleSource = parserContext.extractSource(element);
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
createBeanDefEntry(AssertMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(BackgroundFlushingMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(BtreeIndexCounters.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(ConnectionMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(GlobalLockMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(MemoryMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(OperationCounters.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(ServerInfo.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(MongoAdmin.class, compositeDef, mongoRefName, eleSource, parserContext);
parserContext.registerComponent(compositeDef);
}
protected void createBeanDefEntry(Class<?> clazz, CompositeComponentDefinition compositeDef, String mongoRefName,
Object eleSource, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
builder.getRawBeanDefinition().setSource(eleSource);
builder.addConstructorArgReference(mongoRefName);
BeanDefinition assertDef = builder.getBeanDefinition();
String assertName = parserContext.getReaderContext().registerWithGeneratedName(assertDef);
compositeDef.addNestedComponent(new BeanComponentDefinition(assertDef, assertName));
}
}
/*
* 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.config;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.data.mongodb.core.MongoAdmin;
import org.springframework.data.mongodb.monitor.*;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
public class MongoJmxParser implements BeanDefinitionParser {
public BeanDefinition parse(Element element, ParserContext parserContext) {
String name = element.getAttribute("mongo-ref");
if (!StringUtils.hasText(name)) {
name = "mongo";
}
registerJmxComponents(name, element, parserContext);
return null;
}
protected void registerJmxComponents(String mongoRefName, Element element, ParserContext parserContext) {
Object eleSource = parserContext.extractSource(element);
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
createBeanDefEntry(AssertMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(BackgroundFlushingMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(BtreeIndexCounters.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(ConnectionMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(GlobalLockMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(MemoryMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(OperationCounters.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(ServerInfo.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(MongoAdmin.class, compositeDef, mongoRefName, eleSource, parserContext);
parserContext.registerComponent(compositeDef);
}
protected void createBeanDefEntry(Class<?> clazz, CompositeComponentDefinition compositeDef, String mongoRefName,
Object eleSource, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
builder.getRawBeanDefinition().setSource(eleSource);
builder.addConstructorArgReference(mongoRefName);
BeanDefinition assertDef = builder.getBeanDefinition();
String assertName = parserContext.getReaderContext().registerWithGeneratedName(assertDef);
compositeDef.addNestedComponent(new BeanComponentDefinition(assertDef, assertName));
}
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2011-2015 the original author or authors.
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2011-2015 the original author or authors.
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,

View File

@@ -1,206 +1,207 @@
/*
* Copyright 2011-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.config;
import static org.springframework.data.config.ParsingUtils.*;
import java.util.Map;
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.ManagedMap;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.data.mongodb.core.MongoClientOptionsFactoryBean;
import org.springframework.data.mongodb.core.MongoOptionsFactoryBean;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
/**
* Utility methods for {@link BeanDefinitionParser} implementations for MongoDB.
*
* @author Mark Pollack
* @author Oliver Gierke
* @author Thomas Darimont
* @author Christoph Strobl
*/
@SuppressWarnings("deprecation")
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:options} sub-element. Populates the given attribute factory with the proper attributes.
*
* @return true if parsing actually occured, {@literal false} otherwise
*/
static boolean parseMongoOptions(Element element, BeanDefinitionBuilder mongoBuilder) {
Element optionsElement = DomUtils.getChildElementByTagName(element, "options");
if (optionsElement == null) {
return false;
}
BeanDefinitionBuilder optionsDefBuilder = BeanDefinitionBuilder
.genericBeanDefinition(MongoOptionsFactoryBean.class);
setPropertyValue(optionsDefBuilder, optionsElement, "connections-per-host", "connectionsPerHost");
setPropertyValue(optionsDefBuilder, optionsElement, "threads-allowed-to-block-for-connection-multiplier",
"threadsAllowedToBlockForConnectionMultiplier");
setPropertyValue(optionsDefBuilder, optionsElement, "max-wait-time", "maxWaitTime");
setPropertyValue(optionsDefBuilder, optionsElement, "connect-timeout", "connectTimeout");
setPropertyValue(optionsDefBuilder, optionsElement, "socket-timeout", "socketTimeout");
setPropertyValue(optionsDefBuilder, optionsElement, "socket-keep-alive", "socketKeepAlive");
setPropertyValue(optionsDefBuilder, optionsElement, "auto-connect-retry", "autoConnectRetry");
setPropertyValue(optionsDefBuilder, optionsElement, "max-auto-connect-retry-time", "maxAutoConnectRetryTime");
setPropertyValue(optionsDefBuilder, optionsElement, "write-number", "writeNumber");
setPropertyValue(optionsDefBuilder, optionsElement, "write-timeout", "writeTimeout");
setPropertyValue(optionsDefBuilder, optionsElement, "write-fsync", "writeFsync");
setPropertyValue(optionsDefBuilder, optionsElement, "slave-ok", "slaveOk");
setPropertyValue(optionsDefBuilder, optionsElement, "ssl", "ssl");
setPropertyReference(optionsDefBuilder, optionsElement, "ssl-socket-factory-ref", "sslSocketFactory");
mongoBuilder.addPropertyValue("mongoOptions", optionsDefBuilder.getBeanDefinition());
return true;
}
/**
* Parses the {@code mongo:client-options} 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}.
* @return
* @since 1.7
*/
public static boolean parseMongoClientOptions(Element element, BeanDefinitionBuilder mongoClientBuilder) {
Element optionsElement = DomUtils.getChildElementByTagName(element, "client-options");
if (optionsElement == 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");
mongoClientBuilder.addPropertyValue("mongoClientOptions", clientOptionsDefBuilder.getBeanDefinition());
return true;
}
/**
* Returns the {@link BeanDefinitionBuilder} to build a {@link BeanDefinition} for a
* {@link WriteConcernPropertyEditor}.
*
* @return
*/
static BeanDefinitionBuilder getWriteConcernPropertyEditorBuilder() {
Map<String, Class<?>> customEditors = new ManagedMap<String, Class<?>>();
customEditors.put("com.mongodb.WriteConcern", WriteConcernPropertyEditor.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
* container.
*/
static BeanDefinitionBuilder getServerAddressPropertyEditorBuilder() {
Map<String, String> customEditors = new ManagedMap<String, String>();
customEditors.put("com.mongodb.ServerAddress[]",
"org.springframework.data.mongodb.config.ServerAddressPropertyEditor");
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class);
builder.addPropertyValue("customEditors", customEditors);
return builder;
}
/**
* Returns the {@link BeanDefinitionBuilder} to build a {@link BeanDefinition} for a
* {@link ReadPreferencePropertyEditor}.
*
* @return
* @since 1.7
*/
static BeanDefinitionBuilder getReadPreferencePropertyEditorBuilder() {
Map<String, Class<?>> customEditors = new ManagedMap<String, Class<?>>();
customEditors.put("com.mongodb.ReadPreference", ReadPreferencePropertyEditor.class);
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class);
builder.addPropertyValue("customEditors", customEditors);
return builder;
}
/**
* Returns the {@link BeanDefinitionBuilder} to build a {@link BeanDefinition} for a
* {@link MongoCredentialPropertyEditor}.
*
* @return
* @since 1.7
*/
static BeanDefinitionBuilder getMongoCredentialPropertyEditor() {
Map<String, Class<?>> customEditors = new ManagedMap<String, Class<?>>();
customEditors.put("com.mongodb.MongoCredential[]", MongoCredentialPropertyEditor.class);
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class);
builder.addPropertyValue("customEditors", customEditors);
return builder;
}
}
/*
* 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.config;
import static org.springframework.data.config.ParsingUtils.*;
import java.util.Map;
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.ManagedMap;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.data.mongodb.core.MongoClientOptionsFactoryBean;
import org.springframework.data.mongodb.core.MongoOptionsFactoryBean;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
/**
* Utility methods for {@link BeanDefinitionParser} implementations for MongoDB.
*
* @author Mark Pollack
* @author Oliver Gierke
* @author Thomas Darimont
* @author Christoph Strobl
*/
@SuppressWarnings("deprecation")
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:options} sub-element. Populates the given attribute factory with the proper attributes.
*
* @return true if parsing actually occured, {@literal false} otherwise
*/
static boolean parseMongoOptions(Element element, BeanDefinitionBuilder mongoBuilder) {
Element optionsElement = DomUtils.getChildElementByTagName(element, "options");
if (optionsElement == null) {
return false;
}
BeanDefinitionBuilder optionsDefBuilder = BeanDefinitionBuilder
.genericBeanDefinition(MongoOptionsFactoryBean.class);
setPropertyValue(optionsDefBuilder, optionsElement, "connections-per-host", "connectionsPerHost");
setPropertyValue(optionsDefBuilder, optionsElement, "threads-allowed-to-block-for-connection-multiplier",
"threadsAllowedToBlockForConnectionMultiplier");
setPropertyValue(optionsDefBuilder, optionsElement, "max-wait-time", "maxWaitTime");
setPropertyValue(optionsDefBuilder, optionsElement, "connect-timeout", "connectTimeout");
setPropertyValue(optionsDefBuilder, optionsElement, "socket-timeout", "socketTimeout");
setPropertyValue(optionsDefBuilder, optionsElement, "socket-keep-alive", "socketKeepAlive");
setPropertyValue(optionsDefBuilder, optionsElement, "auto-connect-retry", "autoConnectRetry");
setPropertyValue(optionsDefBuilder, optionsElement, "max-auto-connect-retry-time", "maxAutoConnectRetryTime");
setPropertyValue(optionsDefBuilder, optionsElement, "write-number", "writeNumber");
setPropertyValue(optionsDefBuilder, optionsElement, "write-timeout", "writeTimeout");
setPropertyValue(optionsDefBuilder, optionsElement, "write-fsync", "writeFsync");
setPropertyValue(optionsDefBuilder, optionsElement, "slave-ok", "slaveOk");
setPropertyValue(optionsDefBuilder, optionsElement, "ssl", "ssl");
setPropertyReference(optionsDefBuilder, optionsElement, "ssl-socket-factory-ref", "sslSocketFactory");
mongoBuilder.addPropertyValue("mongoOptions", optionsDefBuilder.getBeanDefinition());
return true;
}
/**
* Parses the {@code mongo:client-options} 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}.
* @return
* @since 1.7
*/
public static boolean parseMongoClientOptions(Element element, BeanDefinitionBuilder mongoClientBuilder) {
Element optionsElement = DomUtils.getChildElementByTagName(element, "client-options");
if (optionsElement == 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");
setPropertyValue(clientOptionsDefBuilder, optionsElement, "server-selection-timeout", "serverSelectionTimeout");
mongoClientBuilder.addPropertyValue("mongoClientOptions", clientOptionsDefBuilder.getBeanDefinition());
return true;
}
/**
* Returns the {@link BeanDefinitionBuilder} to build a {@link BeanDefinition} for a
* {@link WriteConcernPropertyEditor}.
*
* @return
*/
static BeanDefinitionBuilder getWriteConcernPropertyEditorBuilder() {
Map<String, Class<?>> customEditors = new ManagedMap<String, Class<?>>();
customEditors.put("com.mongodb.WriteConcern", WriteConcernPropertyEditor.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
* container.
*/
static BeanDefinitionBuilder getServerAddressPropertyEditorBuilder() {
Map<String, String> customEditors = new ManagedMap<String, String>();
customEditors.put("com.mongodb.ServerAddress[]",
"org.springframework.data.mongodb.config.ServerAddressPropertyEditor");
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class);
builder.addPropertyValue("customEditors", customEditors);
return builder;
}
/**
* Returns the {@link BeanDefinitionBuilder} to build a {@link BeanDefinition} for a
* {@link ReadPreferencePropertyEditor}.
*
* @return
* @since 1.7
*/
static BeanDefinitionBuilder getReadPreferencePropertyEditorBuilder() {
Map<String, Class<?>> customEditors = new ManagedMap<String, Class<?>>();
customEditors.put("com.mongodb.ReadPreference", ReadPreferencePropertyEditor.class);
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class);
builder.addPropertyValue("customEditors", customEditors);
return builder;
}
/**
* Returns the {@link BeanDefinitionBuilder} to build a {@link BeanDefinition} for a
* {@link MongoCredentialPropertyEditor}.
*
* @return
* @since 1.7
*/
static BeanDefinitionBuilder getMongoCredentialPropertyEditor() {
Map<String, Class<?>> customEditors = new ManagedMap<String, Class<?>>();
customEditors.put("com.mongodb.MongoCredential[]", MongoCredentialPropertyEditor.class);
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class);
builder.addPropertyValue("customEditors", customEditors);
return builder;
}
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2011-2014 the original author or authors.
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2015 the original author or authors.
* Copyright 2015-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
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2011-2013 the original author or authors.
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2012 the original author or authors.
* Copyright 2012-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
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2011 the original author or authors.
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,

View File

@@ -0,0 +1,121 @@
/*
* 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.AllArgsConstructor;
import java.util.List;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationOperationContext;
import org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext;
import org.springframework.data.mongodb.core.aggregation.TypedAggregation;
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.util.ObjectUtils;
import com.mongodb.BasicDBList;
import com.mongodb.DBObject;
/**
* Utility methods to map {@link org.springframework.data.mongodb.core.aggregation.Aggregation} pipeline definitions and
* create type-bound {@link AggregationOperationContext}.
*
* @author Christoph Strobl
* @author Mark Paluch
* @since 1.10.13
*/
@AllArgsConstructor
class AggregationUtil {
QueryMapper queryMapper;
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> 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
* information (is a {@link TypedAggregation}) or use the {@link Aggregation#DEFAULT_CONTEXT}.
*
* @param aggregation must not be {@literal null}.
* @param context can be {@literal null}.
* @return the root {@link AggregationOperationContext} to use.
*/
AggregationOperationContext prepareAggregationContext(Aggregation aggregation, AggregationOperationContext context) {
if (context != null) {
return context;
}
if (aggregation instanceof TypedAggregation) {
return new TypeBasedAggregationOperationContext(((TypedAggregation) aggregation).getInputType(), mappingContext,
queryMapper);
}
return Aggregation.DEFAULT_CONTEXT;
}
/**
* Extract and map the aggregation pipeline into a {@link List} of {@link Document}.
*
* @param aggregation
* @param context
* @return
*/
DBObject createPipeline(String collectionName, Aggregation aggregation, AggregationOperationContext context) {
if (!ObjectUtils.nullSafeEquals(context, Aggregation.DEFAULT_CONTEXT)) {
return aggregation.toDbObject(collectionName, context);
}
DBObject command = aggregation.toDbObject(collectionName, context);
command.put("pipeline", mapAggregationPipeline((List) command.get("pipeline")));
return command;
}
/**
* Extract the command and map the aggregation pipeline.
*
* @param aggregation
* @param context
* @return
*/
DBObject createCommand(String collection, Aggregation aggregation, AggregationOperationContext context) {
DBObject command = aggregation.toDbObject(collection, context);
if (!ObjectUtils.nullSafeEquals(context, Aggregation.DEFAULT_CONTEXT)) {
return command;
}
command.put("pipeline", mapAggregationPipeline((List) command.get("pipeline")));
return command;
}
private BasicDBList mapAggregationPipeline(List<DBObject> pipeline) {
BasicDBList mapped = new BasicDBList();
for (DBObject stage : pipeline) {
mapped.add(queryMapper.getMappedObject(stage, null));
}
return mapped;
}
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2015-2016 the original author or authors.
* Copyright 2015-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
* 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,
@@ -28,7 +28,7 @@ import com.mongodb.BulkWriteResult;
* 2.6 and make use of low level bulk commands on the protocol level. This interface defines a fluent API to add
* multiple single operations or list of similar operations in sequence which can then eventually be executed by calling
* {@link #execute()}.
*
*
* @author Tobias Trelle
* @author Oliver Gierke
* @since 1.9
@@ -49,7 +49,7 @@ public interface BulkOperations {
/**
* Add a single insert to the bulk operation.
*
*
* @param documents the document to insert, must not be {@literal null}.
* @return the current {@link BulkOperations} instance with the insert added, will never be {@literal null}.
*/
@@ -57,7 +57,7 @@ public interface BulkOperations {
/**
* Add a list of inserts to the bulk operation.
*
*
* @param documents List of documents to insert, must not be {@literal null}.
* @return the current {@link BulkOperations} instance with the insert added, will never be {@literal null}.
*/
@@ -65,7 +65,7 @@ public interface BulkOperations {
/**
* Add a single update to the bulk operation. For the update request, only the first matching document is updated.
*
*
* @param query update criteria, must not be {@literal null}.
* @param update {@link Update} operation to perform, must not be {@literal null}.
* @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}.
@@ -74,7 +74,7 @@ public interface BulkOperations {
/**
* Add a list of updates to the bulk operation. For each update request, only the first matching document is updated.
*
*
* @param updates Update operations to perform.
* @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}.
*/
@@ -82,7 +82,7 @@ public interface BulkOperations {
/**
* Add a single update to the bulk operation. For the update request, all matching documents are updated.
*
*
* @param query Update criteria.
* @param update Update operation to perform.
* @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}.
@@ -91,7 +91,7 @@ public interface BulkOperations {
/**
* 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}.
@@ -101,7 +101,7 @@ public interface BulkOperations {
/**
* Add a single upsert to the bulk operation. An upsert is an update if the set of matching documents is not empty,
* else an insert.
*
*
* @param query Update criteria.
* @param update Update operation to perform.
* @return The bulk operation.
@@ -112,7 +112,7 @@ public interface BulkOperations {
/**
* Add a list of upserts to the bulk operation. An upsert is an update if the set of matching documents is not empty,
* 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}.
@@ -121,7 +121,7 @@ public interface BulkOperations {
/**
* Add a single remove operation to the bulk operation.
*
*
* @param remove the {@link Query} to select the documents to be removed, must not be {@literal null}.
* @return the current {@link BulkOperations} instance with the removal added, will never be {@literal null}.
*/
@@ -129,7 +129,7 @@ public interface BulkOperations {
/**
* Add a list of remove operations to the bulk operation.
*
*
* @param removes the remove operations to perform, must not be {@literal null}.
* @return the current {@link BulkOperations} instance with the removal added, will never be {@literal null}.
*/
@@ -137,9 +137,9 @@ public interface BulkOperations {
/**
* Execute all bulk operations using the default write concern.
*
*
* @return Result of the bulk operation providing counters for inserts/updates etc.
* @throws {@link BulkOperationException} if an error occurred during bulk processing.
* @throws org.springframework.data.mongodb.BulkOperationException if an error occurred during bulk processing.
*/
BulkWriteResult execute();
}

View File

@@ -1,26 +1,26 @@
/*
* Copyright 2010-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.core;
import com.mongodb.DBCollection;
import com.mongodb.MongoException;
import org.springframework.dao.DataAccessException;
public interface CollectionCallback<T> {
T doInCollection(DBCollection collection) throws MongoException, DataAccessException;
}
/*
* Copyright 2010-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 com.mongodb.DBCollection;
import com.mongodb.MongoException;
import org.springframework.dao.DataAccessException;
public interface CollectionCallback<T> {
T doInCollection(DBCollection collection) throws MongoException, DataAccessException;
}

View File

@@ -1,70 +1,70 @@
/*
* Copyright 2010-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.core;
/**
* Provides a simple wrapper to encapsulate the variety of settings you can use when creating a collection.
*
* @author Thomas Risberg
*/
public class CollectionOptions {
private Integer maxDocuments;
private Integer size;
private Boolean capped;
/**
* Constructs a new <code>CollectionOptions</code> instance.
*
* @param size the collection size in bytes, this data space is preallocated
* @param maxDocuments the maximum number of documents in the collection.
* @param capped true to created a "capped" collection (fixed size with auto-FIFO behavior based on insertion order),
* false otherwise.
*/
public CollectionOptions(Integer size, Integer maxDocuments, Boolean capped) {
super();
this.maxDocuments = maxDocuments;
this.size = size;
this.capped = capped;
}
public Integer getMaxDocuments() {
return maxDocuments;
}
public void setMaxDocuments(Integer maxDocuments) {
this.maxDocuments = maxDocuments;
}
public Integer getSize() {
return size;
}
public void setSize(Integer size) {
this.size = size;
}
public Boolean getCapped() {
return capped;
}
public void setCapped(Boolean capped) {
this.capped = capped;
}
}
/*
* Copyright 2010-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;
/**
* Provides a simple wrapper to encapsulate the variety of settings you can use when creating a collection.
*
* @author Thomas Risberg
*/
public class CollectionOptions {
private Integer maxDocuments;
private Integer size;
private Boolean capped;
/**
* Constructs a new <code>CollectionOptions</code> instance.
*
* @param size the collection size in bytes, this data space is preallocated
* @param maxDocuments the maximum number of documents in the collection.
* @param capped true to created a "capped" collection (fixed size with auto-FIFO behavior based on insertion order),
* false otherwise.
*/
public CollectionOptions(Integer size, Integer maxDocuments, Boolean capped) {
super();
this.maxDocuments = maxDocuments;
this.size = size;
this.capped = capped;
}
public Integer getMaxDocuments() {
return maxDocuments;
}
public void setMaxDocuments(Integer maxDocuments) {
this.maxDocuments = maxDocuments;
}
public Integer getSize() {
return size;
}
public void setSize(Integer size) {
this.size = size;
}
public Boolean getCapped() {
return capped;
}
public void setCapped(Boolean capped) {
this.capped = capped;
}
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-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
* 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,

View File

@@ -1,25 +1,25 @@
/*
* Copyright 2010-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.core;
import com.mongodb.DB;
import com.mongodb.MongoException;
import org.springframework.dao.DataAccessException;
public interface DbCallback<T> {
T doInDB(DB db) throws MongoException, DataAccessException;
}
/*
* Copyright 2010-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 com.mongodb.DB;
import com.mongodb.MongoException;
import org.springframework.dao.DataAccessException;
public interface DbCallback<T> {
T doInDB(DB db) throws MongoException, DataAccessException;
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2015-2016 the original author or authors.
* Copyright 2015-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
* 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,
@@ -15,16 +15,23 @@
*/
package org.springframework.data.mongodb.core;
import java.util.Arrays;
import lombok.NonNull;
import lombok.Value;
import java.util.Collections;
import java.util.List;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.support.PersistenceExceptionTranslator;
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.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.util.Pair;
import org.springframework.util.Assert;
import com.mongodb.BasicDBObject;
import com.mongodb.BulkWriteException;
import com.mongodb.BulkWriteOperation;
import com.mongodb.BulkWriteRequestBuilder;
@@ -35,17 +42,18 @@ import com.mongodb.WriteConcern;
/**
* Default implementation for {@link BulkOperations}.
*
*
* @author Tobias Trelle
* @author Oliver Gierke
* @author Christoph Strobl
* @author Mark Paluch
* @since 1.9
*/
class DefaultBulkOperations implements BulkOperations {
private final MongoOperations mongoOperations;
private final BulkMode bulkMode;
private final String collectionName;
private final Class<?> entityType;
private final BulkOperationContext bulkOperationContext;
private PersistenceExceptionTranslator exceptionTranslator;
private WriteConcernResolver writeConcernResolver;
@@ -54,35 +62,32 @@ class DefaultBulkOperations implements BulkOperations {
private BulkWriteOperation bulk;
/**
* Creates a new {@link DefaultBulkOperations} for the given {@link MongoOperations}, {@link BulkMode}, collection
* name and {@link WriteConcern}.
*
* @param mongoOperations The underlying {@link MongoOperations}, must not be {@literal null}.
* @param bulkMode must not be {@literal null}.
* @param collectionName Name of the collection to work on, must not be {@literal null} or empty.
* @param entityType the entity type, can be {@literal null}.
* Creates a new {@link DefaultBulkOperations} for the given {@link MongoOperations}, collection name and
* {@link BulkOperationContext}.
*
* @param mongoOperations must not be {@literal null}.
* @param collectionName must not be {@literal null}.
* @param bulkOperationContext must not be {@literal null}.
* @since 1.10.5
*/
DefaultBulkOperations(MongoOperations mongoOperations, BulkMode bulkMode, String collectionName,
Class<?> entityType) {
DefaultBulkOperations(MongoOperations mongoOperations, String collectionName,
BulkOperationContext bulkOperationContext) {
Assert.notNull(mongoOperations, "MongoOperations must not be null!");
Assert.notNull(bulkMode, "BulkMode must not be null!");
Assert.hasText(collectionName, "Collection name must not be null or empty!");
Assert.hasText(collectionName, "CollectionName must not be null nor empty!");
Assert.notNull(bulkOperationContext, "BulkOperationContext must not be null!");
this.mongoOperations = mongoOperations;
this.bulkMode = bulkMode;
this.collectionName = collectionName;
this.entityType = entityType;
this.bulkOperationContext = bulkOperationContext;
this.exceptionTranslator = new MongoExceptionTranslator();
this.writeConcernResolver = DefaultWriteConcernResolver.INSTANCE;
this.bulk = initBulkOperation();
this.bulk = getBulkWriteOptions(bulkOperationContext.getBulkMode());
}
/**
* Configures the {@link PersistenceExceptionTranslator} to be used. Defaults to {@link MongoExceptionTranslator}.
*
*
* @param exceptionTranslator can be {@literal null}.
*/
public void setExceptionTranslator(PersistenceExceptionTranslator exceptionTranslator) {
@@ -91,7 +96,7 @@ class DefaultBulkOperations implements BulkOperations {
/**
* Configures the {@link WriteConcernResolver} to be used. Defaults to {@link DefaultWriteConcernResolver}.
*
*
* @param writeConcernResolver can be {@literal null}.
*/
public void setWriteConcernResolver(WriteConcernResolver writeConcernResolver) {
@@ -101,10 +106,10 @@ class DefaultBulkOperations implements BulkOperations {
/**
* Configures the default {@link WriteConcern} to be used. Defaults to {@literal null}.
*
*
* @param defaultWriteConcern can be {@literal null}.
*/
public void setDefaultWriteConcern(WriteConcern defaultWriteConcern) {
void setDefaultWriteConcern(WriteConcern defaultWriteConcern) {
this.defaultWriteConcern = defaultWriteConcern;
}
@@ -117,7 +122,15 @@ class DefaultBulkOperations implements BulkOperations {
Assert.notNull(document, "Document must not be null!");
bulk.insert((DBObject) mongoOperations.getConverter().convertToMongoType(document));
if (document instanceof DBObject) {
bulk.insert((DBObject) document);
return this;
}
DBObject sink = new BasicDBObject();
mongoOperations.getConverter().write(document, sink);
bulk.insert(sink);
return this;
}
@@ -148,7 +161,7 @@ class DefaultBulkOperations implements BulkOperations {
Assert.notNull(query, "Query must not be null!");
Assert.notNull(update, "Update must not be null!");
return updateOne(Arrays.asList(Pair.of(query, update)));
return updateOne(Collections.singletonList(Pair.of(query, update)));
}
/*
@@ -178,7 +191,7 @@ class DefaultBulkOperations implements BulkOperations {
Assert.notNull(query, "Query must not be null!");
Assert.notNull(update, "Update must not be null!");
return updateMulti(Arrays.asList(Pair.of(query, update)));
return updateMulti(Collections.singletonList(Pair.of(query, update)));
}
/*
@@ -229,7 +242,7 @@ class DefaultBulkOperations implements BulkOperations {
Assert.notNull(query, "Query must not be null!");
bulk.find(query.getQueryObject()).remove();
bulk.find(getMappedQuery(query.getQueryObject())).remove();
return this;
}
@@ -257,27 +270,25 @@ class DefaultBulkOperations implements BulkOperations {
@Override
public BulkWriteResult execute() {
MongoAction action = new MongoAction(defaultWriteConcern, MongoActionOperation.BULK, collectionName, entityType,
null, null);
MongoAction action = new MongoAction(defaultWriteConcern, MongoActionOperation.BULK, collectionName,
bulkOperationContext.getEntityType(), null, null);
WriteConcern writeConcern = writeConcernResolver.resolve(action);
try {
return writeConcern == null ? bulk.execute() : bulk.execute(writeConcern);
} catch (BulkWriteException o_O) {
DataAccessException toThrow = exceptionTranslator.translateExceptionIfPossible(o_O);
throw toThrow == null ? o_O : toThrow;
} finally {
this.bulk = initBulkOperation();
this.bulk = getBulkWriteOptions(bulkOperationContext.getBulkMode());
}
}
/**
* Performs update and upsert bulk operations.
*
*
* @param query the {@link Query} to determine documents to update.
* @param update the {@link Update} to perform, must not be {@literal null}.
* @param upsert whether to upsert.
@@ -289,29 +300,37 @@ class DefaultBulkOperations implements BulkOperations {
Assert.notNull(query, "Query must not be null!");
Assert.notNull(update, "Update must not be null!");
BulkWriteRequestBuilder builder = bulk.find(query.getQueryObject());
BulkWriteRequestBuilder builder = bulk.find(getMappedQuery(query.getQueryObject()));
if (upsert) {
if (multi) {
builder.upsert().update(update.getUpdateObject());
builder.upsert().update(getMappedUpdate(update.getUpdateObject()));
} else {
builder.upsert().updateOne(update.getUpdateObject());
builder.upsert().updateOne(getMappedUpdate(update.getUpdateObject()));
}
} else {
if (multi) {
builder.update(update.getUpdateObject());
builder.update(getMappedUpdate(update.getUpdateObject()));
} else {
builder.updateOne(update.getUpdateObject());
builder.updateOne(getMappedUpdate(update.getUpdateObject()));
}
}
return this;
}
private final BulkWriteOperation initBulkOperation() {
private DBObject getMappedUpdate(DBObject update) {
return bulkOperationContext.getUpdateMapper().getMappedObject(update, bulkOperationContext.getEntity());
}
private DBObject getMappedQuery(DBObject query) {
return bulkOperationContext.getQueryMapper().getMappedObject(query, bulkOperationContext.getEntity());
}
private BulkWriteOperation getBulkWriteOptions(BulkMode bulkMode) {
DBCollection collection = mongoOperations.getCollection(collectionName);
@@ -324,4 +343,25 @@ class DefaultBulkOperations implements BulkOperations {
throw new IllegalStateException("BulkMode was null!");
}
/**
* {@link BulkOperationContext} holds information about
* {@link org.springframework.data.mongodb.core.BulkOperations.BulkMode} the entity in use as well as references to
* {@link QueryMapper} and {@link UpdateMapper}.
*
* @author Christoph Strobl
* @since 2.0
*/
@Value
static class BulkOperationContext {
@NonNull BulkMode bulkMode;
MongoPersistentEntity<?> entity;
@NonNull QueryMapper queryMapper;
@NonNull UpdateMapper updateMapper;
Class<?> getEntityType() {
return entity != null ? entity.getType() : null;
}
}
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2011-2015 the original author or authors.
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -15,17 +15,15 @@
*/
package org.springframework.data.mongodb.core;
import static org.springframework.data.domain.Sort.Direction.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.springframework.dao.DataAccessException;
import org.springframework.data.mongodb.core.convert.QueryMapper;
import org.springframework.data.mongodb.core.index.IndexDefinition;
import org.springframework.data.mongodb.core.index.IndexField;
import org.springframework.data.mongodb.core.index.IndexInfo;
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.util.Assert;
import com.mongodb.DBCollection;
@@ -42,12 +40,12 @@ import com.mongodb.MongoException;
*/
public class DefaultIndexOperations implements IndexOperations {
private static final Double ONE = Double.valueOf(1);
private static final Double MINUS_ONE = Double.valueOf(-1);
private static final Collection<String> TWO_D_IDENTIFIERS = Arrays.asList("2d", "2dsphere");
private static final String PARTIAL_FILTER_EXPRESSION_KEY = "partialFilterExpression";
private final MongoOperations mongoOperations;
private final String collectionName;
private final QueryMapper mapper;
private final Class<?> type;
/**
* Creates a new {@link DefaultIndexOperations}.
@@ -56,12 +54,26 @@ public class DefaultIndexOperations implements IndexOperations {
* @param collectionName must not be {@literal null}.
*/
public DefaultIndexOperations(MongoOperations mongoOperations, String collectionName) {
this(mongoOperations, collectionName, null);
}
/**
* Creates a new {@link DefaultIndexOperations}.
*
* @param mongoOperations must not be {@literal null}.
* @param collectionName must not be {@literal null}.
* @param type Type used for mapping potential partial index filter expression. Can be {@literal null}.
* @since 1.10
*/
public DefaultIndexOperations(MongoOperations mongoOperations, String collectionName, Class<?> type) {
Assert.notNull(mongoOperations, "MongoOperations must not be null!");
Assert.notNull(collectionName, "Collection name can not be null!");
this.mongoOperations = mongoOperations;
this.collectionName = collectionName;
this.mapper = new QueryMapper(mongoOperations.getConverter());
this.type = type;
}
/*
@@ -69,9 +81,20 @@ public class DefaultIndexOperations implements IndexOperations {
* @see org.springframework.data.mongodb.core.IndexOperations#ensureIndex(org.springframework.data.mongodb.core.index.IndexDefinition)
*/
public void ensureIndex(final IndexDefinition indexDefinition) {
mongoOperations.execute(collectionName, new CollectionCallback<Object>() {
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
DBObject indexOptions = indexDefinition.getIndexOptions();
if (indexOptions != null && indexOptions.containsField(PARTIAL_FILTER_EXPRESSION_KEY)) {
Assert.isInstanceOf(DBObject.class, indexOptions.get(PARTIAL_FILTER_EXPRESSION_KEY));
indexOptions.put(PARTIAL_FILTER_EXPRESSION_KEY,
mapper.getMappedObject((DBObject) indexOptions.get(PARTIAL_FILTER_EXPRESSION_KEY),
lookupPersistentEntity(type, collectionName)));
}
if (indexOptions != null) {
collection.createIndex(indexDefinition.getIndexKeys(), indexOptions);
} else {
@@ -79,6 +102,24 @@ public class DefaultIndexOperations implements IndexOperations {
}
return null;
}
private MongoPersistentEntity<?> lookupPersistentEntity(Class<?> entityType, String collection) {
if (entityType != null) {
return mongoOperations.getConverter().getMappingContext().getPersistentEntity(entityType);
}
Collection<? extends MongoPersistentEntity<?>> entities = mongoOperations.getConverter().getMappingContext()
.getPersistentEntities();
for (MongoPersistentEntity<?> entity : entities) {
if (entity.getCollection().equals(collection)) {
return entity;
}
}
return null;
}
});
}
@@ -126,7 +167,9 @@ public class DefaultIndexOperations implements IndexOperations {
public List<IndexInfo> getIndexInfo() {
return mongoOperations.execute(collectionName, new CollectionCallback<List<IndexInfo>>() {
public List<IndexInfo> doInCollection(DBCollection collection) throws MongoException, DataAccessException {
List<DBObject> dbObjectList = collection.getIndexInfo();
return getIndexData(dbObjectList);
}
@@ -136,44 +179,7 @@ public class DefaultIndexOperations implements IndexOperations {
List<IndexInfo> indexInfoList = new ArrayList<IndexInfo>();
for (DBObject ix : dbObjectList) {
DBObject keyDbObject = (DBObject) ix.get("key");
int numberOfElements = keyDbObject.keySet().size();
List<IndexField> indexFields = new ArrayList<IndexField>(numberOfElements);
for (String key : keyDbObject.keySet()) {
Object value = keyDbObject.get(key);
if (TWO_D_IDENTIFIERS.contains(value)) {
indexFields.add(IndexField.geo(key));
} else if ("text".equals(value)) {
DBObject weights = (DBObject) ix.get("weights");
for (String fieldName : weights.keySet()) {
indexFields.add(IndexField.text(fieldName, Float.valueOf(weights.get(fieldName).toString())));
}
} else {
Double keyValue = new Double(value.toString());
if (ONE.equals(keyValue)) {
indexFields.add(IndexField.create(key, ASC));
} else if (MINUS_ONE.equals(keyValue)) {
indexFields.add(IndexField.create(key, DESC));
}
}
}
String name = ix.get("name").toString();
boolean unique = ix.containsField("unique") ? (Boolean) ix.get("unique") : false;
boolean dropDuplicates = ix.containsField("dropDups") ? (Boolean) ix.get("dropDups") : false;
boolean sparse = ix.containsField("sparse") ? (Boolean) ix.get("sparse") : false;
String language = ix.containsField("default_language") ? (String) ix.get("default_language") : "";
indexInfoList.add(new IndexInfo(indexFields, name, unique, dropDuplicates, sparse, language));
indexInfoList.add(IndexInfo.indexInfoOf(ix));
}
return indexInfoList;

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-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
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2015 the original author or authors.
* Copyright 2015-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
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2010-2011 the original author or authors.
* Copyright 2010-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
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2010-2011 the original author or authors.
* Copyright 2010-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
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2016 the original author or authors.
* Copyright 2016-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
* 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,
@@ -62,7 +62,7 @@ class GeoCommandStatistics {
* didn't return any result introduced in MongoDB 3.2 RC1.
*
* @return
* @see https://jira.mongodb.org/browse/SERVER-21024
* @see <a href="https://jira.mongodb.org/browse/SERVER-21024">MongoDB Jira SERVER-21024</a>
*/
public double getAverageDistance() {

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2015 the original author or authors.
* Copyright 2015-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
* 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,
@@ -17,15 +17,14 @@ package org.springframework.data.mongodb.core;
import org.springframework.context.annotation.Bean;
import org.springframework.data.mongodb.core.geo.GeoJsonModule;
import org.springframework.data.web.config.SpringDataWebConfigurationMixin;
import org.springframework.data.web.config.SpringDataJacksonModules;
/**
* Configuration class to expose {@link GeoJsonModule} as a Spring bean.
*
* @author Oliver Gierke
*/
@SpringDataWebConfigurationMixin
public class GeoJsonConfiguration {
public class GeoJsonConfiguration implements SpringDataJacksonModules {
@Bean
public GeoJsonModule geoJsonModule() {

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2011-2015 the original author or authors.
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2011-2012 the original author or authors.
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2011-2015 the original author or authors.
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,

View File

@@ -1,89 +1,91 @@
/*
* Copyright 2011-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.core;
import org.springframework.data.authentication.UserCredentials;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.util.Assert;
import com.mongodb.DB;
import com.mongodb.Mongo;
/**
* Mongo server administration exposed via JMX annotations
*
* @author Mark Pollack
/*
* 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.core;
import org.springframework.data.authentication.UserCredentials;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.util.Assert;
import com.mongodb.DB;
import com.mongodb.Mongo;
/**
* Mongo server administration exposed via JMX annotations
*
* @author Mark Pollack
* @author Thomas Darimont
*/
@ManagedResource(description = "Mongo Admin Operations")
public class MongoAdmin implements MongoAdminOperations {
private final Mongo mongo;
private String username;
private String password;
* @author Mark Paluch
*/
@ManagedResource(description = "Mongo Admin Operations")
public class MongoAdmin implements MongoAdminOperations {
private final Mongo mongo;
private String username;
private String password;
private String authenticationDatabaseName;
public MongoAdmin(Mongo mongo) {
Assert.notNull(mongo);
this.mongo = mongo;
}
/* (non-Javadoc)
* @see org.springframework.data.mongodb.core.core.MongoAdminOperations#dropDatabase(java.lang.String)
*/
@ManagedOperation
public void dropDatabase(String databaseName) {
getDB(databaseName).dropDatabase();
}
/* (non-Javadoc)
* @see org.springframework.data.mongodb.core.core.MongoAdminOperations#createDatabase(java.lang.String)
*/
@ManagedOperation
public void createDatabase(String databaseName) {
getDB(databaseName);
}
/* (non-Javadoc)
* @see org.springframework.data.mongodb.core.core.MongoAdminOperations#getDatabaseStats(java.lang.String)
*/
@ManagedOperation
public String getDatabaseStats(String databaseName) {
return getDB(databaseName).getStats().toString();
}
/**
* Sets the username to use to connect to the Mongo database
*
* @param username The username to use
*/
public void setUsername(String username) {
this.username = username;
}
/**
* Sets the password to use to authenticate with the Mongo database.
*
* @param password The password to use
*/
public void setPassword(String password) {
this.password = password;
}
public MongoAdmin(Mongo mongo) {
Assert.notNull(mongo, "Mongo must not be null!");
this.mongo = mongo;
}
/* (non-Javadoc)
* @see org.springframework.data.mongodb.core.core.MongoAdminOperations#dropDatabase(java.lang.String)
*/
@ManagedOperation
public void dropDatabase(String databaseName) {
getDB(databaseName).dropDatabase();
}
/* (non-Javadoc)
* @see org.springframework.data.mongodb.core.core.MongoAdminOperations#createDatabase(java.lang.String)
*/
@ManagedOperation
public void createDatabase(String databaseName) {
getDB(databaseName);
}
/* (non-Javadoc)
* @see org.springframework.data.mongodb.core.core.MongoAdminOperations#getDatabaseStats(java.lang.String)
*/
@ManagedOperation
public String getDatabaseStats(String databaseName) {
return getDB(databaseName).getStats().toString();
}
/**
* Sets the username to use to connect to the Mongo database
*
* @param username The username to use
*/
public void setUsername(String username) {
this.username = username;
}
/**
* Sets the password to use to authenticate with the Mongo database.
*
* @param password The password to use
*/
public void setPassword(String password) {
this.password = password;
}
/**
* Sets the authenticationDatabaseName to use to authenticate with the Mongo database.
*
@@ -93,7 +95,7 @@ public class MongoAdmin implements MongoAdminOperations {
this.authenticationDatabaseName = authenticationDatabaseName;
}
DB getDB(String databaseName) {
DB getDB(String databaseName) {
return MongoDbUtils.getDB(mongo, databaseName, new UserCredentials(username, password), authenticationDatabaseName);
}
}
}
}

View File

@@ -1,34 +1,34 @@
/*
* Copyright 2011-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.core;
import org.springframework.jmx.export.annotation.ManagedOperation;
/**
* @author Mark Pollack
* @author Oliver Gierke
*/
public interface MongoAdminOperations {
@ManagedOperation
void dropDatabase(String databaseName);
@ManagedOperation
void createDatabase(String databaseName);
@ManagedOperation
String getDatabaseStats(String databaseName);
}
/*
* 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.core;
import org.springframework.jmx.export.annotation.ManagedOperation;
/**
* @author Mark Pollack
* @author Oliver Gierke
*/
public interface MongoAdminOperations {
@ManagedOperation
void dropDatabase(String databaseName);
@ManagedOperation
void createDatabase(String databaseName);
@ManagedOperation
String getDatabaseStats(String databaseName);
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2015 the original author or authors.
* Copyright 2015-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
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2015 the original author or authors.
* Copyright 2015-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
* 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,
@@ -18,8 +18,10 @@ package org.springframework.data.mongodb.core;
import javax.net.SocketFactory;
import javax.net.ssl.SSLSocketFactory;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.factory.config.AbstractFactoryBean;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.util.MongoClientVersion;
import com.mongodb.DBDecoderFactory;
import com.mongodb.DBEncoderFactory;
@@ -30,7 +32,7 @@ import com.mongodb.WriteConcern;
/**
* A factory bean for construction of a {@link MongoClientOptions} instance.
*
*
* @author Christoph Strobl
* @author Oliver Gierke
* @since 1.7
@@ -62,13 +64,14 @@ public class MongoClientOptionsFactoryBean extends AbstractFactoryBean<MongoClie
private int heartbeatConnectTimeout = DEFAULT_MONGO_OPTIONS.getHeartbeatConnectTimeout();
private int heartbeatSocketTimeout = DEFAULT_MONGO_OPTIONS.getHeartbeatSocketTimeout();
private String requiredReplicaSetName = DEFAULT_MONGO_OPTIONS.getRequiredReplicaSetName();
private int serverSelectionTimeout = Integer.MIN_VALUE;
private boolean ssl;
private SSLSocketFactory sslSocketFactory;
/**
* Set the {@link MongoClient} description.
*
*
* @param description
*/
public void setDescription(String description) {
@@ -77,7 +80,7 @@ public class MongoClientOptionsFactoryBean extends AbstractFactoryBean<MongoClie
/**
* Set the minimum number of connections per host.
*
*
* @param minConnectionsPerHost
*/
public void setMinConnectionsPerHost(int minConnectionsPerHost) {
@@ -87,7 +90,7 @@ public class MongoClientOptionsFactoryBean extends AbstractFactoryBean<MongoClie
/**
* 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) {
@@ -98,7 +101,7 @@ public class MongoClientOptionsFactoryBean extends AbstractFactoryBean<MongoClie
* 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) {
@@ -107,7 +110,7 @@ public class MongoClientOptionsFactoryBean extends AbstractFactoryBean<MongoClie
/**
* 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) {
@@ -116,7 +119,7 @@ public class MongoClientOptionsFactoryBean extends AbstractFactoryBean<MongoClie
/**
* The maximum idle time for a pooled connection.
*
*
* @param maxConnectionIdleTime
*/
public void setMaxConnectionIdleTime(int maxConnectionIdleTime) {
@@ -125,7 +128,7 @@ public class MongoClientOptionsFactoryBean extends AbstractFactoryBean<MongoClie
/**
* Set the maximum life time for a pooled connection.
*
*
* @param maxConnectionLifeTime
*/
public void setMaxConnectionLifeTime(int maxConnectionLifeTime) {
@@ -134,7 +137,7 @@ public class MongoClientOptionsFactoryBean extends AbstractFactoryBean<MongoClie
/**
* Set the connect timeout in milliseconds. 0 is default and infinite.
*
*
* @param connectTimeout
*/
public void setConnectTimeout(int connectTimeout) {
@@ -143,7 +146,7 @@ public class MongoClientOptionsFactoryBean extends AbstractFactoryBean<MongoClie
/**
* Set the socket timeout. 0 is default and infinite.
*
*
* @param socketTimeout
*/
public void setSocketTimeout(int socketTimeout) {
@@ -152,7 +155,7 @@ public class MongoClientOptionsFactoryBean extends AbstractFactoryBean<MongoClie
/**
* 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) {
@@ -161,7 +164,7 @@ public class MongoClientOptionsFactoryBean extends AbstractFactoryBean<MongoClie
/**
* Set the {@link ReadPreference}.
*
*
* @param readPreference
*/
public void setReadPreference(ReadPreference readPreference) {
@@ -171,7 +174,7 @@ public class MongoClientOptionsFactoryBean extends AbstractFactoryBean<MongoClie
/**
* 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(WriteConcern writeConcern) {
@@ -187,7 +190,7 @@ public class MongoClientOptionsFactoryBean extends AbstractFactoryBean<MongoClie
/**
* 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) {
@@ -197,7 +200,7 @@ public class MongoClientOptionsFactoryBean extends AbstractFactoryBean<MongoClie
/**
* 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) {
@@ -206,7 +209,7 @@ public class MongoClientOptionsFactoryBean extends AbstractFactoryBean<MongoClie
/**
* Set the connect timeout for connections used for the cluster heartbeat.
*
*
* @param heartbeatConnectTimeout
*/
public void setHeartbeatConnectTimeout(int heartbeatConnectTimeout) {
@@ -215,7 +218,7 @@ public class MongoClientOptionsFactoryBean extends AbstractFactoryBean<MongoClie
/**
* Set the socket timeout for connections used for the cluster heartbeat.
*
*
* @param heartbeatSocketTimeout
*/
public void setHeartbeatSocketTimeout(int heartbeatSocketTimeout) {
@@ -224,7 +227,7 @@ public class MongoClientOptionsFactoryBean extends AbstractFactoryBean<MongoClie
/**
* Configures the name of the replica set.
*
*
* @param requiredReplicaSetName
*/
public void setRequiredReplicaSetName(String requiredReplicaSetName) {
@@ -233,7 +236,7 @@ public class MongoClientOptionsFactoryBean extends AbstractFactoryBean<MongoClie
/**
* This controls if the driver should us an SSL connection. Defaults to |@literal false}.
*
*
* @param ssl
*/
public void setSsl(boolean ssl) {
@@ -243,24 +246,41 @@ public class MongoClientOptionsFactoryBean extends AbstractFactoryBean<MongoClie
/**
* 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(SSLSocketFactory sslSocketFactory) {
this.sslSocketFactory = sslSocketFactory;
}
/*
/**
* 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;
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.config.AbstractFactoryBean#createInstance()
*/
@Override
protected MongoClientOptions createInstance() throws Exception {
SocketFactory socketFactoryToUse = ssl ? (sslSocketFactory != null ? sslSocketFactory : SSLSocketFactory
.getDefault()) : this.socketFactory;
SocketFactory socketFactoryToUse = ssl
? (sslSocketFactory != null ? sslSocketFactory : SSLSocketFactory.getDefault()) : this.socketFactory;
return MongoClientOptions.builder() //
MongoClientOptions.Builder builder = MongoClientOptions.builder();
if (MongoClientVersion.isMongo3Driver() && serverSelectionTimeout != Integer.MIN_VALUE) {
new DirectFieldAccessor(builder).setPropertyValue("serverSelectionTimeout", serverSelectionTimeout);
}
return builder //
.alwaysUseMBeans(this.alwaysUseMBeans) //
.connectionsPerHost(this.connectionsPerHost) //
.connectTimeout(connectTimeout) //

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2013 the original author or authors.
* Copyright 2013-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
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2010-2015 the original author or authors.
* Copyright 2010-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
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2010-2015 the original author or authors.
* Copyright 2010-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
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2010-2015 the original author or authors.
* Copyright 2010-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
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2011-2015 the original author or authors.
*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -48,7 +48,7 @@ import com.mongodb.WriteResult;
* 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).
*
*
* @author Thomas Risberg
* @author Mark Pollack
* @author Oliver Gierke
@@ -61,7 +61,7 @@ public interface MongoOperations {
/**
* The collection name used for the specified class by this template.
*
*
* @param entityClass must not be {@literal null}.
* @return
*/
@@ -71,7 +71,7 @@ public interface MongoOperations {
* Execute the a MongoDB command expressed as a JSON string. This will call the method JSON.parse that is part of the
* MongoDB driver to convert the JSON string to a DBObject. Any errors that result from executing this command will be
* converted into Spring's DAO exception hierarchy.
*
*
* @param jsonCommand a MongoDB command expressed as a JSON string.
*/
CommandResult executeCommand(String jsonCommand);
@@ -79,7 +79,7 @@ public interface MongoOperations {
/**
* Execute a MongoDB command. Any errors that result from executing this command will be converted into Spring's DAO
* exception hierarchy.
*
*
* @param command a MongoDB command
*/
CommandResult executeCommand(DBObject command);
@@ -87,7 +87,7 @@ public interface MongoOperations {
/**
* Execute a MongoDB command. Any errors that result from executing this command will be converted into Spring's DAO
* exception hierarchy.
*
*
* @param command a MongoDB command
* @param options query options to use
* @deprecated since 1.7. Please use {@link #executeCommand(DBObject, ReadPreference)}, as the MongoDB Java driver
@@ -99,7 +99,7 @@ public interface MongoOperations {
/**
* Execute a MongoDB command. Any errors that result from executing this command will be converted into Spring's data
* access exception hierarchy.
*
*
* @param command a MongoDB command, must not be {@literal null}.
* @param readPreference read preferences to use, can be {@literal null}.
* @return
@@ -109,7 +109,7 @@ public interface MongoOperations {
/**
* Execute a MongoDB query and iterate over the query results on a per-document basis with a DocumentCallbackHandler.
*
*
* @param query the query class that specifies the criteria used to find a record and also an optional fields
* specification
* @param collectionName name of the collection to retrieve the objects from
@@ -121,7 +121,7 @@ public interface MongoOperations {
* Executes a {@link DbCallback} translating any exceptions as necessary.
* <p/>
* Allows for returning a result object, that is a domain object or a collection of domain objects.
*
*
* @param <T> return type
* @param action callback object that specifies the MongoDB actions to perform on the passed in DB instance.
* @return a result object returned by the action or <tt>null</tt>
@@ -132,7 +132,7 @@ public interface MongoOperations {
* Executes the given {@link CollectionCallback} on the entity collection of the specified class.
* <p/>
* 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
* @param <T> return type
* @param action callback object that specifies the MongoDB action
@@ -144,7 +144,7 @@ public interface MongoOperations {
* Executes the given {@link CollectionCallback} on the collection of the given name.
* <p/>
* Allows for returning a result object, that is a domain object or a collection of domain objects.
*
*
* @param <T> return type
* @param collectionName the name of the collection that specifies which DBCollection instance will be passed into
* @param action callback object that specifies the MongoDB action the callback action.
@@ -158,7 +158,7 @@ public interface MongoOperations {
* href=http://www.mongodb.org/display/DOCS/Java+Driver+Concurrency>Java Driver Concurrency</a>}
* <p/>
* Allows for returning a result object, that is a domain object or a collection of domain objects.
*
*
* @param <T> return type
* @param action callback that specified the MongoDB actions to perform on the DB instance
* @return a result object returned by the action or <tt>null</tt>
@@ -173,7 +173,7 @@ public interface MongoOperations {
* {@link Cursor}.
* <p>
* Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link Cursor} that needs to be closed.
*
*
* @param <T> element return type
* @param query must not be {@literal null}.
* @param entityType must not be {@literal null}.
@@ -187,7 +187,7 @@ public interface MongoOperations {
* by a Mongo DB {@link Cursor}.
* <p>
* Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link Cursor} that needs to be closed.
*
*
* @param <T> element return type
* @param query must not be {@literal null}.
* @param entityType must not be {@literal null}.
@@ -199,7 +199,7 @@ public interface MongoOperations {
/**
* Create an uncapped collection with a name based on the provided entity class.
*
*
* @param entityClass class that determines the collection to create
* @return the created collection
*/
@@ -207,7 +207,7 @@ public interface MongoOperations {
/**
* Create a collection with a name based on the provided entity class using the options.
*
*
* @param entityClass class that determines the collection to create
* @param collectionOptions options to use when creating the collection.
* @return the created collection
@@ -216,7 +216,7 @@ public interface MongoOperations {
/**
* Create an uncapped collection with the provided name.
*
*
* @param collectionName name of the collection
* @return the created collection
*/
@@ -224,7 +224,7 @@ public interface MongoOperations {
/**
* Create a collection with the provided name and options.
*
*
* @param collectionName name of the collection
* @param collectionOptions options to use when creating the collection.
* @return the created collection
@@ -233,7 +233,7 @@ public interface MongoOperations {
/**
* A set of collection names.
*
*
* @return list of collection names
*/
Set<String> getCollectionNames();
@@ -242,7 +242,7 @@ public interface MongoOperations {
* Get a collection by name, creating it if it doesn't exist.
* <p/>
* Translate any exceptions as necessary.
*
*
* @param collectionName name of the collection
* @return an existing collection or a newly created one.
*/
@@ -252,7 +252,7 @@ public interface MongoOperations {
* Check to see if a collection with a name indicated by the entity class exists.
* <p/>
* Translate any exceptions as necessary.
*
*
* @param entityClass class that determines the name of the collection
* @return true if a collection with the given name is found, false otherwise.
*/
@@ -262,7 +262,7 @@ public interface MongoOperations {
* Check to see if a collection with a given name exists.
* <p/>
* Translate any exceptions as necessary.
*
*
* @param collectionName name of the collection
* @return true if a collection with the given name is found, false otherwise.
*/
@@ -272,7 +272,7 @@ public interface MongoOperations {
* Drop the collection with the name indicated by the entity class.
* <p/>
* Translate any exceptions as necessary.
*
*
* @param entityClass class that determines the collection to drop/delete.
*/
<T> void dropCollection(Class<T> entityClass);
@@ -281,36 +281,39 @@ public interface MongoOperations {
* Drop the collection with the given name.
* <p/>
* Translate any exceptions as necessary.
*
*
* @param collectionName name of the collection to drop/delete.
*/
void dropCollection(String collectionName);
/**
* Returns the operations that can be performed on indexes
*
*
* @return index operations on the named collection
*/
IndexOperations indexOps(String collectionName);
/**
* Returns the operations that can be performed on indexes
*
*
* @return index operations on the named collection associated with the given entity class
*/
IndexOperations indexOps(Class<?> entityClass);
/**
* Returns the {@link ScriptOperations} that can be performed on {@link com.mongodb.DB} level.
*
*
* @return
* @since 1.7
*/
ScriptOperations scriptOps();
/**
* Returns a new {@link BulkOperations} for the given collection.
*
* Returns a new {@link BulkOperations} for the given collection. <br />
* <strong>NOTE:</strong> Any additional support for field mapping, etc. is not available for {@literal update} or
* {@literal remove} operations in bulk mode due to the lack of domain type information. Use
* {@link #bulkOps(BulkMode, Class, String)} to get full type specific support.
*
* @param mode the {@link BulkMode} to use for bulk operations, must not be {@literal null}.
* @param collectionName the name of the collection to work on, must not be {@literal null} or empty.
* @return {@link BulkOperations} on the named collection
@@ -319,7 +322,7 @@ public interface MongoOperations {
/**
* Returns a new {@link BulkOperations} for the given entity type.
*
*
* @param mode the {@link BulkMode} to use for bulk operations, must not be {@literal null}.
* @param entityType the name of the entity class, must not be {@literal null}.
* @return {@link BulkOperations} on the named collection associated of the given entity class.
@@ -328,7 +331,7 @@ public interface MongoOperations {
/**
* Returns a new {@link BulkOperations} for the given entity type and collection name.
*
*
* @param mode the {@link BulkMode} to use for bulk operations, must not be {@literal null}.
* @param entityClass the name of the entity class, must not be {@literal null}.
* @param collectionName the name of the collection to work on, must not be {@literal null} or empty.
@@ -344,7 +347,7 @@ public interface MongoOperations {
* <p/>
* 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.
*
*
* @param entityClass the parameterized type of the returned list
* @return the converted collection
*/
@@ -358,7 +361,7 @@ public interface MongoOperations {
* <p/>
* 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.
*
*
* @param entityClass the parameterized type of the returned list.
* @param collectionName name of the collection to retrieve the objects from
* @return the converted collection
@@ -368,7 +371,7 @@ public interface MongoOperations {
/**
* Execute a group operation over the entire collection. The group operation entity class should match the 'shape' of
* the returned object that takes int account the initial document structure as well as any finalize functions.
*
*
* @param criteria The criteria that restricts the row that are considered for grouping. If not specified all rows are
* considered.
* @param inputCollectionName the collection where the group operation will read from
@@ -383,7 +386,7 @@ public interface MongoOperations {
* Execute a group operation restricting the rows to those which match the provided Criteria. The group operation
* entity class should match the 'shape' of the returned object that takes int account the initial document structure
* as well as any finalize functions.
*
*
* @param criteria The criteria that restricts the row that are considered for grouping. If not specified all rows are
* considered.
* @param inputCollectionName the collection where the group operation will read from
@@ -397,7 +400,7 @@ public interface MongoOperations {
/**
* Execute an aggregation operation. The raw results will be mapped to the given entity class. The name of the
* inputCollection is derived from the inputType of the aggregation.
*
*
* @param aggregation The {@link TypedAggregation} specification holding the aggregation operations, must not be
* {@literal null}.
* @param collectionName The name of the input collection to use for the aggreation.
@@ -410,7 +413,7 @@ public interface MongoOperations {
/**
* Execute an aggregation operation. The raw results will be mapped to the given entity class. The name of the
* inputCollection is derived from the inputType of the aggregation.
*
*
* @param aggregation The {@link TypedAggregation} specification holding the aggregation operations, must not be
* {@literal null}.
* @param outputType The parameterized type of the returned list, must not be {@literal null}.
@@ -421,7 +424,7 @@ public interface MongoOperations {
/**
* Execute an aggregation operation. The raw results will be mapped to the given entity class.
*
*
* @param aggregation The {@link Aggregation} specification holding the aggregation operations, must not be
* {@literal null}.
* @param inputType the inputType where the aggregation operation will read from, must not be {@literal null} or
@@ -434,7 +437,7 @@ public interface MongoOperations {
/**
* Execute an aggregation operation. The raw results will be mapped to the given entity class.
*
*
* @param aggregation The {@link Aggregation} specification holding the aggregation operations, must not be
* {@literal null}.
* @param collectionName the collection where the aggregation operation will read from, must not be {@literal null} or
@@ -447,7 +450,7 @@ public interface MongoOperations {
/**
* Execute a map-reduce operation. The map-reduce operation will be formed with an output type of INLINE
*
*
* @param inputCollectionName the collection where the map-reduce will read from
* @param mapFunction The JavaScript map function
* @param reduceFunction The JavaScript reduce function
@@ -460,7 +463,7 @@ public interface MongoOperations {
/**
* Execute a map-reduce operation that takes additional map-reduce options.
*
*
* @param inputCollectionName the collection where the map-reduce will read from
* @param mapFunction The JavaScript map function
* @param reduceFunction The JavaScript reduce function
@@ -474,7 +477,7 @@ public interface MongoOperations {
/**
* Execute a map-reduce operation that takes a query. The map-reduce operation will be formed with an output type of
* INLINE
*
*
* @param query The query to use to select the data for the map phase
* @param inputCollectionName the collection where the map-reduce will read from
* @param mapFunction The JavaScript map function
@@ -488,7 +491,7 @@ public interface MongoOperations {
/**
* Execute a map-reduce operation that takes a query and additional map-reduce options
*
*
* @param query The query to use to select the data for the map phase
* @param inputCollectionName the collection where the map-reduce will read from
* @param mapFunction The JavaScript map function
@@ -505,7 +508,7 @@ public interface MongoOperations {
* information to determine the collection the query is ran against. Note, that MongoDB limits the number of results
* by default. Make sure to add an explicit limit to the {@link NearQuery} if you expect a particular number of
* results.
*
*
* @param near must not be {@literal null}.
* @param entityClass must not be {@literal null}.
* @return
@@ -516,7 +519,7 @@ public interface MongoOperations {
* Returns {@link GeoResults} for all entities matching the given {@link NearQuery}. Note, that MongoDB limits the
* number of results by default. Make sure to add an explicit limit to the {@link NearQuery} if you expect a
* particular number of results.
*
*
* @param near must not be {@literal null}.
* @param entityClass must not be {@literal null}.
* @param collectionName the collection to trigger the query against. If no collection name is given the entity class
@@ -534,7 +537,7 @@ public interface MongoOperations {
* <p/>
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
*
* @param query the query class that specifies the criteria used to find a record and also an optional fields
* specification
* @param entityClass the parameterized type of the returned list.
@@ -551,7 +554,7 @@ public interface MongoOperations {
* <p/>
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
*
* @param query the query class that specifies the criteria used to find a record and also an optional fields
* specification
* @param entityClass the parameterized type of the returned list.
@@ -561,8 +564,10 @@ public interface MongoOperations {
<T> T findOne(Query query, Class<T> entityClass, String collectionName);
/**
* Determine result of given {@link Query} contains at least one element.
*
* Determine result of given {@link Query} contains at least one element. <br />
* <strong>NOTE:</strong> Any additional support for query/field mapping, etc. is not available due to the lack of
* domain type information. Use {@link #exists(Query, Class, String)} to get full type specific support.
*
* @param query the {@link Query} class that specifies the criteria used to find a record.
* @param collectionName name of the collection to check for objects.
* @return
@@ -571,7 +576,7 @@ public interface MongoOperations {
/**
* Determine result of given {@link Query} contains at least one element.
*
*
* @param query the {@link Query} class that specifies the criteria used to find a record.
* @param entityClass the parameterized type.
* @return
@@ -580,7 +585,7 @@ public interface MongoOperations {
/**
* Determine result of given {@link Query} contains at least one element.
*
*
* @param query the {@link Query} class that specifies the criteria used to find a record.
* @param entityClass the parameterized type.
* @param collectionName name of the collection to check for objects.
@@ -596,7 +601,7 @@ public interface MongoOperations {
* <p/>
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
*
* @param query the query class that specifies the criteria used to find a record and also an optional fields
* specification
* @param entityClass the parameterized type of the returned list.
@@ -612,7 +617,7 @@ public interface MongoOperations {
* <p/>
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
*
* @param query the query class that specifies the criteria used to find a record and also an optional fields
* specification
* @param entityClass the parameterized type of the returned list.
@@ -624,7 +629,7 @@ public interface MongoOperations {
/**
* Returns a document with the given id mapped onto the given class. The collection the query is ran against will be
* derived from the given target class as well.
*
*
* @param <T>
* @param id the id of the document to return.
* @param entityClass the type the document shall be converted into.
@@ -634,7 +639,7 @@ public interface MongoOperations {
/**
* Returns the document with the given id from the given collection mapped onto the given target class.
*
*
* @param id the id of the document to return
* @param entityClass the type to convert the document to
* @param collectionName the collection to query for the document
@@ -644,9 +649,9 @@ public interface MongoOperations {
<T> T findById(Object id, Class<T> entityClass, String collectionName);
/**
* Triggers <a href="http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify
* <a/> to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query}.
*
* Triggers <a href="http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify <a/>
* 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
* fields specification.
* @param update the {@link Update} to apply on matching documents.
@@ -656,9 +661,9 @@ public interface MongoOperations {
<T> T findAndModify(Query query, Update update, Class<T> entityClass);
/**
* Triggers <a href="http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify
* <a/> to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query}.
*
* Triggers <a href="http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify <a/>
* 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
* fields specification.
* @param update the {@link Update} to apply on matching documents.
@@ -669,10 +674,10 @@ public interface MongoOperations {
<T> T findAndModify(Query query, Update update, Class<T> entityClass, String collectionName);
/**
* Triggers <a href="http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify
* <a/> to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query} taking
* Triggers <a href="http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify <a/>
* to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query} taking
* {@link FindAndModifyOptions} into account.
*
*
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional
* fields specification.
* @param update the {@link Update} to apply on matching documents.
@@ -683,10 +688,10 @@ public interface MongoOperations {
<T> T findAndModify(Query query, Update update, FindAndModifyOptions options, Class<T> entityClass);
/**
* Triggers <a href="http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify
* <a/> to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query} taking
* Triggers <a href="http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify <a/>
* to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query} taking
* {@link FindAndModifyOptions} into account.
*
*
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional
* fields specification.
* @param update the {@link Update} to apply on matching documents.
@@ -707,7 +712,7 @@ public interface MongoOperations {
* <p/>
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
*
* @param query the query class that specifies the criteria used to find a record and also an optional fields
* specification
* @param entityClass the parameterized type of the returned list.
@@ -724,7 +729,7 @@ public interface MongoOperations {
* <p/>
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
*
* @param query the query class that specifies the criteria used to find a record and also an optional fields
* specification
* @param entityClass the parameterized type of the returned list.
@@ -735,7 +740,7 @@ public interface MongoOperations {
/**
* Returns the number of documents for the given {@link Query} by querying the collection of the given entity class.
*
*
* @param query
* @param entityClass must not be {@literal null}.
* @return
@@ -745,8 +750,8 @@ public interface MongoOperations {
/**
* Returns the number of documents for the given {@link Query} querying the given collection. The given {@link Query}
* must solely consist of document field references as we lack type information to map potential property references
* onto document fields. TO make sure the query gets mapped, use {@link #count(Query, Class, String)}.
*
* onto document fields. Use {@link #count(Query, Class, String)} to get full type specific support.
*
* @param query
* @param collectionName must not be {@literal null} or empty.
* @return
@@ -757,7 +762,7 @@ public interface MongoOperations {
/**
* 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}.
*
*
* @param query
* @param entityClass must not be {@literal null}.
* @param collectionName must not be {@literal null} or empty.
@@ -778,7 +783,7 @@ public interface MongoOperations {
* <p/>
* <p/>
* 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.
*/
void insert(Object objectToSave);
@@ -790,7 +795,7 @@ public interface MongoOperations {
* configured otherwise, an instance of MappingMongoConverter will be used.
* <p/>
* 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
* @param collectionName name of the collection to store the object in
*/
@@ -798,7 +803,7 @@ public interface MongoOperations {
/**
* Insert a Collection of objects into a collection in a single batch write to the database.
*
*
* @param batchToSave the list of objects to save.
* @param entityClass class that determines the collection to use
*/
@@ -806,7 +811,7 @@ public interface MongoOperations {
/**
* Insert a list of objects into the specified collection in a single batch write to the database.
*
*
* @param batchToSave the list of objects to save.
* @param collectionName name of the collection to store the object in
*/
@@ -815,8 +820,8 @@ public interface MongoOperations {
/**
* Insert a mixed Collection of objects into a database collection determining the collection name to use based on the
* class.
*
* @param collectionToSave the list of objects to save.
*
* @param objectsToSave the list of objects to save.
*/
void insertAll(Collection<? extends Object> objectsToSave);
@@ -832,7 +837,7 @@ public interface MongoOperations {
* property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See
* <a href="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html#core-convert" >
* Spring's Type Conversion"</a> for more details.
*
*
* @param objectToSave the object to store in the collection
*/
void save(Object objectToSave);
@@ -849,7 +854,7 @@ public interface MongoOperations {
* property type will be handled by Spring's BeanWrapper class that leverages Type Cobnversion API. See <a
* http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html#core-convert">Spring's
* Type Conversion"</a> for more details.
*
*
* @param objectToSave the object to store in the collection
* @param collectionName name of the collection to store the object in
*/
@@ -858,7 +863,7 @@ public interface MongoOperations {
/**
* Performs an upsert. If no document is found that matches the query, a new document is created and inserted by
* combining the query document and the update document.
*
*
* @param query the query document that specifies the criteria used to select a record to be upserted
* @param update the update document that contains the updated object or $ operators to manipulate the existing object
* @param entityClass class that determines the collection to use
@@ -868,8 +873,10 @@ public interface MongoOperations {
/**
* Performs an upsert. If no document is found that matches the query, a new document is created and inserted by
* combining the query document and the update document.
*
* combining the query document and the update document. <br />
* <strong>NOTE:</strong> Any additional support for field mapping, versions, etc. is not available due to the lack of
* domain type information. Use {@link #upsert(Query, Update, Class, String)} to get full type specific support.
*
* @param query the query document that specifies the criteria used to select a record to be updated
* @param update the update document that contains the updated object or $ operators to manipulate the existing
* object.
@@ -881,7 +888,7 @@ public interface MongoOperations {
/**
* Performs an upsert. If no document is found that matches the query, a new document is created and inserted by
* combining the query document and the update document.
*
*
* @param query the query document that specifies the criteria used to select a record to be upserted
* @param update the update document that contains the updated object or $ operators to manipulate the existing object
* @param entityClass class of the pojo to be operated on
@@ -893,7 +900,7 @@ public interface MongoOperations {
/**
* Updates the first object that is found in the collection of the entity class that matches the query document with
* the provided update document.
*
*
* @param query the query document that specifies the criteria used to select a record to be updated
* @param update the update document that contains the updated object or $ operators to manipulate the existing
* object.
@@ -904,8 +911,10 @@ public interface MongoOperations {
/**
* Updates the first object that is found in the specified collection that matches the query document criteria with
* the provided updated document.
*
* the provided updated document. <br />
* <strong>NOTE:</strong> Any additional support for field mapping, versions, etc. is not available due to the lack of
* domain type information. Use {@link #updateFirst(Query, Update, Class, String)} to get full type specific support.
*
* @param query the query document that specifies the criteria used to select a record to be updated
* @param update the update document that contains the updated object or $ operators to manipulate the existing
* object.
@@ -917,7 +926,7 @@ public interface MongoOperations {
/**
* Updates the first object that is found in the specified collection that matches the query document criteria with
* the provided updated document.
*
*
* @param query the query document that specifies the criteria used to select a record to be updated
* @param update the update document that contains the updated object or $ operators to manipulate the existing
* object.
@@ -930,7 +939,7 @@ public interface MongoOperations {
/**
* Updates all objects that are found in the collection for the entity class that matches the query document criteria
* with the provided updated document.
*
*
* @param query the query document that specifies the criteria used to select a record to be updated
* @param update the update document that contains the updated object or $ operators to manipulate the existing
* object.
@@ -941,8 +950,10 @@ public interface MongoOperations {
/**
* Updates all objects that are found in the specified collection that matches the query document criteria with the
* provided updated document.
*
* provided updated document. <br />
* <strong>NOTE:</strong> Any additional support for field mapping, versions, etc. is not available due to the lack of
* domain type information. Use {@link #updateMulti(Query, Update, Class, String)} to get full type specific support.
*
* @param query the query document that specifies the criteria used to select a record to be updated
* @param update the update document that contains the updated object or $ operators to manipulate the existing
* object.
@@ -954,7 +965,7 @@ public interface MongoOperations {
/**
* Updates all objects that are found in the collection for the entity class that matches the query document criteria
* with the provided updated document.
*
*
* @param query the query document that specifies the criteria used to select a record to be updated
* @param update the update document that contains the updated object or $ operators to manipulate the existing
* object.
@@ -966,14 +977,14 @@ public interface MongoOperations {
/**
* Remove the given object from the collection by id.
*
*
* @param object
*/
WriteResult remove(Object object);
/**
* Removes the given object from the given collection.
*
*
* @param object
* @param collection must not be {@literal null} or empty.
*/
@@ -982,36 +993,44 @@ public interface MongoOperations {
/**
* Remove all documents that match the provided query document criteria from the the collection used to store the
* entityClass. The Class parameter is also used to help convert the Id of the object if it is present in the query.
*
* @param query
* @param entityClass
*
* @param query must not be {@literal null}.
* @param entityClass must not be {@literal null}.
* @throws IllegalArgumentException when {@literal query} or {@literal entityClass} is {@literal null}.
*/
WriteResult remove(Query query, Class<?> entityClass);
/**
* Remove all documents that match the provided query document criteria from the the collection used to store the
* entityClass. The Class parameter is also used to help convert the Id of the object if it is present in the query.
*
*
* @param query
* @param entityClass
* @param collectionName
* @throws IllegalArgumentException when {@literal query}, {@literal entityClass} or {@literal collectionName} is
* {@literal null}.
*/
WriteResult remove(Query query, Class<?> entityClass, String collectionName);
/**
* Remove all documents from the specified collection that match the provided query document criteria. There is no
* conversion/mapping done for any criteria using the id field.
*
* conversion/mapping done for any criteria using the id field. <br />
* <strong>NOTE:</strong> Any additional support for field mapping is not available due to the lack of domain type
* information. Use {@link #remove(Query, Class, String)} to get full type specific support.
*
* @param query the query document that specifies the criteria used to remove a record
* @param collectionName name of the collection where the objects will removed
* @throws IllegalArgumentException when {@literal query} or {@literal collectionName} is {@literal null}.
*/
WriteResult remove(Query query, String collectionName);
/**
* Returns and removes all documents form the specified collection that match the provided query.
*
* @param query
* @param collectionName
* Returns and removes all documents form the specified collection that match the provided query. <br />
* <strong>NOTE:</strong> Any additional support for field mapping is not available due to the lack of domain type
* information. Use {@link #findAllAndRemove(Query, Class, String)} to get full type specific support.
*
* @param query must not be {@literal null}.
* @param collectionName must not be {@literal null}.
* @return
* @since 1.5
*/
@@ -1019,7 +1038,7 @@ public interface MongoOperations {
/**
* Returns and removes all documents matching the given query form the collection used to store the entityClass.
*
*
* @param query
* @param entityClass
* @return
@@ -1031,7 +1050,7 @@ public interface MongoOperations {
* Returns and removes all documents that match the provided query document criteria from the the collection used to
* store the entityClass. The Class parameter is also used to help convert the Id of the object if it is present in
* the query.
*
*
* @param query
* @param entityClass
* @param collectionName
@@ -1042,7 +1061,7 @@ public interface MongoOperations {
/**
* Returns the underlying {@link MongoConverter}.
*
*
* @return
*/
MongoConverter getConverter();

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2010-2015 the original author or authors.
* Copyright 2010-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
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2012-2014 the original author or authors.
* Copyright 2012-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
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2010-2016 the original author or authors.
* Copyright 2010-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
* 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,
@@ -19,17 +19,8 @@ import static org.springframework.data.mongodb.core.query.Criteria.*;
import static org.springframework.data.mongodb.core.query.SerializationUtils.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.Set;
import org.bson.types.ObjectId;
import org.slf4j.Logger;
@@ -61,12 +52,14 @@ import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.BulkOperations.BulkMode;
import org.springframework.data.mongodb.core.DefaultBulkOperations.BulkOperationContext;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationOperationContext;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.Fields;
import org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext;
import org.springframework.data.mongodb.core.aggregation.TypedAggregation;
import org.springframework.data.mongodb.core.convert.CustomConversions;
import org.springframework.data.mongodb.core.convert.DbRefResolver;
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
@@ -106,27 +99,13 @@ import org.springframework.util.ObjectUtils;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;
import com.mongodb.BasicDBObject;
import com.mongodb.Bytes;
import com.mongodb.CommandResult;
import com.mongodb.Cursor;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.MapReduceCommand;
import com.mongodb.MapReduceOutput;
import com.mongodb.Mongo;
import com.mongodb.MongoException;
import com.mongodb.ReadPreference;
import com.mongodb.WriteConcern;
import com.mongodb.WriteResult;
import com.mongodb.*;
import com.mongodb.util.JSON;
import com.mongodb.util.JSONParseException;
/**
* Primary implementation of {@link MongoOperations}.
*
*
* @author Thomas Risberg
* @author Graeme Rocher
* @author Mark Pollack
@@ -141,6 +120,8 @@ import com.mongodb.util.JSONParseException;
* @author Doménique Tilleuil
* @author Niko Schmuck
* @author Mark Paluch
* @author Laszlo Csontos
* @author Borislav Rangelov
*/
@SuppressWarnings("deprecation")
public class MongoTemplate implements MongoOperations, ApplicationContextAware {
@@ -177,7 +158,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
/**
* Constructor used for a basic template configuration
*
*
* @param mongo must not be {@literal null}.
* @param databaseName must not be {@literal null} or empty.
*/
@@ -188,7 +169,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
/**
* Constructor used for a template configuration with user credentials in the form of
* {@link org.springframework.data.authentication.UserCredentials}
*
*
* @param mongo must not be {@literal null}.
* @param databaseName must not be {@literal null} or empty.
* @param userCredentials
@@ -199,7 +180,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
/**
* Constructor used for a basic template configuration.
*
*
* @param mongoDbFactory must not be {@literal null}.
*/
public MongoTemplate(MongoDbFactory mongoDbFactory) {
@@ -208,13 +189,13 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
/**
* Constructor used for a basic template configuration.
*
*
* @param mongoDbFactory must not be {@literal null}.
* @param mongoConverter
*/
public MongoTemplate(MongoDbFactory mongoDbFactory, MongoConverter mongoConverter) {
Assert.notNull(mongoDbFactory);
Assert.notNull(mongoDbFactory, "MongoDbFactory must not be null!");
this.mongoDbFactory = mongoDbFactory;
this.exceptionTranslator = mongoDbFactory.getExceptionTranslator();
@@ -237,7 +218,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
/**
* Configures the {@link WriteResultChecking} to be used with the template. Setting {@literal null} will reset the
* default of {@value #DEFAULT_WRITE_RESULT_CHECKING}.
*
*
* @param resultChecking
*/
public void setWriteResultChecking(WriteResultChecking resultChecking) {
@@ -248,7 +229,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
* 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.
*
*
* @param writeConcern
*/
public void setWriteConcern(WriteConcern writeConcern) {
@@ -257,7 +238,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
/**
* Configures the {@link WriteConcernResolver} to be used with the template.
*
*
* @param writeConcernResolver
*/
public void setWriteConcernResolver(WriteConcernResolver writeConcernResolver) {
@@ -267,7 +248,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
/**
* Used by @{link {@link #prepareCollection(DBCollection)} to set the {@link ReadPreference} before any operations are
* performed.
*
*
* @param readPreference
*/
public void setReadPreference(ReadPreference readPreference) {
@@ -294,7 +275,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
* they were registered for the current {@link MappingContext}. If no creator for the current {@link MappingContext}
* can be found we manually add the internally created one as {@link ApplicationListener} to make sure indexes get
* created appropriately for entity types persisted through this {@link MongoTemplate} instance.
*
*
* @param context must not be {@literal null}.
*/
private void prepareIndexCreator(ApplicationContext context) {
@@ -314,15 +295,15 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
}
/**
* Returns the default {@link org.springframework.data.mongodb.core.core.convert.MongoConverter}.
*
* Returns the default {@link org.springframework.data.mongodb.core.convert.MongoConverter}.
*
* @return
*/
public MongoConverter getConverter() {
return this.mongoConverter;
}
/*
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.MongoOperations#executeAsStream(org.springframework.data.mongodb.core.query.Query, java.lang.Class)
*/
@@ -332,7 +313,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
return stream(query, entityType, determineCollectionName(entityType));
}
/*
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.MongoOperations#stream(org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String)
*/
@@ -428,7 +409,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
/**
* Execute a MongoDB query and iterate over the query results on a per-document basis with a
* {@link DocumentCallbackHandler} using the provided CursorPreparer.
*
*
* @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}.
* @param collectionName name of the collection to retrieve the objects from
@@ -439,7 +420,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
protected void executeQuery(Query query, String collectionName, DocumentCallbackHandler dch,
CursorPreparer preparer) {
Assert.notNull(query);
Assert.notNull(query, "Query must not be null!");
DBObject queryObject = queryMapper.getMappedObject(query.getQueryObject(), null);
DBObject sortObject = query.getSortObject();
@@ -455,7 +436,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
public <T> T execute(DbCallback<T> action) {
Assert.notNull(action);
Assert.notNull(action, "DbCallbackmust not be null!");
try {
DB db = this.getDb();
@@ -471,7 +452,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
public <T> T execute(String collectionName, CollectionCallback<T> callback) {
Assert.notNull(callback);
Assert.notNull(callback, "CollectionCallback must not be null!");
try {
DBCollection collection = getAndPrepareCollection(getDb(), collectionName);
@@ -557,7 +538,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
}
public IndexOperations indexOps(Class<?> entityClass) {
return new DefaultIndexOperations(this, determineCollectionName(entityClass));
return new DefaultIndexOperations(this, determineCollectionName(entityClass), entityClass);
}
public BulkOperations bulkOps(BulkMode bulkMode, String collectionName) {
@@ -573,10 +554,10 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
Assert.notNull(mode, "BulkMode must not be null!");
Assert.hasText(collectionName, "Collection name must not be null or empty!");
DefaultBulkOperations operations = new DefaultBulkOperations(this, mode, collectionName, entityType);
DefaultBulkOperations operations = new DefaultBulkOperations(this, collectionName,
new BulkOperationContext(mode, getPersistentEntity(entityType), queryMapper, updateMapper));
operations.setExceptionTranslator(exceptionTranslator);
operations.setWriteConcernResolver(writeConcernResolver);
operations.setDefaultWriteConcern(writeConcern);
return operations;
@@ -699,8 +680,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
/*
* As MongoDB currently (2.4.4) doesn't support the skipping of elements in near queries
* we skip the elements ourselves to avoid at least the document 2 object mapping overhead.
*
* @see https://jira.mongodb.org/browse/SERVER-3925
*
* @see <a href="https://jira.mongodb.org/browse/SERVER-3925">MongoDB Jira: SERVER-3925</a>
*/
if (index >= elementsToSkip) {
result.add(callback.doWith((DBObject) element));
@@ -749,7 +730,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
}
public long count(Query query, Class<?> entityClass) {
Assert.notNull(entityClass);
Assert.notNull(entityClass, "Entity class must not be null!");
return count(query, entityClass, determineCollectionName(entityClass));
}
@@ -763,7 +745,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
*/
public long count(Query query, Class<?> entityClass, String collectionName) {
Assert.hasText(collectionName);
Assert.hasText(collectionName, "Collection name must not be null or empty!");
final DBObject dbObject = query == null ? null
: queryMapper.getMappedObject(query.getQueryObject(),
entityClass == null ? null : mappingContext.getPersistentEntity(entityClass));
@@ -804,7 +787,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
/**
* 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.
*
*
* @param collection
*/
protected void prepareCollection(DBCollection collection) {
@@ -818,7 +801,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
* settings in sub-classes. <br />
* In case of using MongoDB Java driver version 3 the returned {@link WriteConcern} will be defaulted to
* {@link WriteConcern#ACKNOWLEDGED} when {@link WriteResultChecking} is set to {@link WriteResultChecking#EXCEPTION}.
*
*
* @param writeConcern any WriteConcern already configured or null
* @return The prepared WriteConcern or null
*/
@@ -842,11 +825,9 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
protected <T> void doInsert(String collectionName, T objectToSave, MongoWriter<T> writer) {
assertUpdateableIdIfNotSet(objectToSave);
initializeVersionProperty(objectToSave);
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave, collectionName));
assertUpdateableIdIfNotSet(objectToSave);
DBObject dbDoc = toDbObject(objectToSave, writer);
@@ -934,15 +915,16 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
protected <T> void doInsertBatch(String collectionName, Collection<? extends T> batchToSave, MongoWriter<T> writer) {
Assert.notNull(writer);
Assert.notNull(writer, "MongoWriter must not be null!");
List<DBObject> dbObjectList = new ArrayList<DBObject>();
for (T o : batchToSave) {
initializeVersionProperty(o);
BasicDBObject dbDoc = new BasicDBObject();
maybeEmitEvent(new BeforeConvertEvent<T>(o, collectionName));
BasicDBObject dbDoc = new BasicDBObject();
writer.write(o, dbDoc);
maybeEmitEvent(new BeforeSaveEvent<T>(o, dbDoc, collectionName));
@@ -963,14 +945,14 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
public void save(Object objectToSave) {
Assert.notNull(objectToSave);
Assert.notNull(objectToSave, "Object to save must not be null!");
save(objectToSave, determineEntityCollectionName(objectToSave));
}
public void save(Object objectToSave, String collectionName) {
Assert.notNull(objectToSave);
Assert.hasText(collectionName);
Assert.notNull(objectToSave, "Object to save must not be null!");
Assert.hasText(collectionName, "Collection name must not be null or empty!");
MongoPersistentEntity<?> mongoPersistentEntity = getPersistentEntity(objectToSave.getClass());
@@ -999,23 +981,23 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
doInsert(collectionName, objectToSave, this.mongoConverter);
} else {
assertUpdateableIdIfNotSet(objectToSave);
// Create query for entity with the id and old version
Object id = convertingAccessor.getProperty(idProperty);
Query query = new Query(Criteria.where(idProperty.getName()).is(id).and(versionProperty.getName()).is(version));
// Bump version number
convertingAccessor.setProperty(versionProperty, versionNumber.longValue() + 1);
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave, collectionName));
assertUpdateableIdIfNotSet(objectToSave);
BasicDBObject dbObject = new BasicDBObject();
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave, collectionName));
this.mongoConverter.write(objectToSave, dbObject);
maybeEmitEvent(new BeforeSaveEvent<T>(objectToSave, dbObject, collectionName));
Update update = Update.fromDBObject(dbObject, ID_FIELD);
// Create query for entity with the id and old version
Object id = convertingAccessor.getProperty(idProperty);
Query query = new Query(Criteria.where(idProperty.getName()).is(id).and(versionProperty.getName()).is(version));
doUpdate(collectionName, query, update, objectToSave.getClass(), false, false);
maybeEmitEvent(new AfterSaveEvent<T>(objectToSave, dbObject, collectionName));
}
@@ -1023,9 +1005,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
protected <T> void doSave(String collectionName, T objectToSave, MongoWriter<T> writer) {
assertUpdateableIdIfNotSet(objectToSave);
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave, collectionName));
assertUpdateableIdIfNotSet(objectToSave);
DBObject dbDoc = toDbObject(objectToSave, writer);
@@ -1216,7 +1197,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
public WriteResult remove(Object object, String collection) {
Assert.hasText(collection);
Assert.hasText(collection, "Collection name must not be null or empty!");
if (object == null) {
return null;
@@ -1228,7 +1209,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
/**
* Returns {@link Entry} containing the field name of the id property as {@link Entry#getKey()} and the {@link Id}s
* property value as its {@link Entry#getValue()}.
*
*
* @param object
* @return
*/
@@ -1255,7 +1236,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
/**
* Returns a {@link Query} for the given entity by its id.
*
*
* @param object must not be {@literal null}.
* @return
*/
@@ -1267,7 +1248,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
/**
* Returns a {@link Query} for the given entities by their ids.
*
*
* @param objects must not be {@literal null} or {@literal empty}.
* @return
*/
@@ -1320,35 +1301,46 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
protected <T> WriteResult doRemove(final String collectionName, final Query query, final Class<T> entityClass) {
if (query == null) {
throw new InvalidDataAccessApiUsageException("Query passed in to remove can't be null!");
}
Assert.notNull(query, "Query must not be null!");
Assert.hasText(collectionName, "Collection name must not be null or empty!");
final DBObject queryObject = query.getQueryObject();
final MongoPersistentEntity<?> entity = getPersistentEntity(entityClass);
final DBObject queryObject = queryMapper.getMappedObject(query.getQueryObject(), entity);
return execute(collectionName, new CollectionCallback<WriteResult>() {
public WriteResult doInCollection(DBCollection collection) throws MongoException, DataAccessException {
maybeEmitEvent(new BeforeDeleteEvent<T>(queryObject, entityClass, collectionName));
DBObject dboq = queryMapper.getMappedObject(queryObject, entity);
DBObject removeQuery = queryObject;
MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.REMOVE, collectionName,
entityClass, null, queryObject);
entityClass, null, removeQuery);
WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Remove using query: {} in collection: {}.",
new Object[] { serializeToJsonSafely(dboq), collectionName });
new Object[] { serializeToJsonSafely(removeQuery), collectionName });
}
WriteResult wr = writeConcernToUse == null ? collection.remove(dboq)
: collection.remove(dboq, writeConcernToUse);
if (query.getLimit() > 0 || query.getSkip() > 0) {
handleAnyWriteResultErrors(wr, dboq, MongoActionOperation.REMOVE);
DBCursor cursor = new QueryCursorPreparer(query, entityClass)
.prepare(collection.find(removeQuery, new BasicDBObject(ID_FIELD, 1)));
Set<Object> ids = new LinkedHashSet<Object>();
Iterator<DBObject> it = cursor.iterator();
while (it.hasNext()) {
ids.add(it.next().get(ID_FIELD));
}
removeQuery = new BasicDBObject(ID_FIELD, new BasicDBObject("$in", ids));
}
WriteResult wr = writeConcernToUse == null ? collection.remove(removeQuery)
: collection.remove(removeQuery, writeConcernToUse);
handleAnyWriteResultErrors(wr, removeQuery, MongoActionOperation.REMOVE);
maybeEmitEvent(new AfterDeleteEvent<T>(queryObject, entityClass, collectionName));
@@ -1513,7 +1505,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
*/
@Override
public <T> List<T> findAllAndRemove(Query query, String collectionName) {
return findAndRemove(query, null, collectionName);
return (List<T>) findAllAndRemove(query, Object.class, collectionName);
}
/*
@@ -1538,7 +1530,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
* Retrieve and remove all documents matching the given {@code query} by calling {@link #find(Query, Class, String)}
* and {@link #remove(Query, Class, String)}, whereas the {@link Query} for {@link #remove(Query, Class, String)} is
* constructed out of the find result.
*
*
* @param collectionName
* @param query
* @param entityClass
@@ -1562,15 +1554,9 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
Assert.notNull(aggregation, "Aggregation pipeline must not be null!");
Assert.notNull(outputType, "Output type must not be null!");
AggregationOperationContext rootContext = context == null ? Aggregation.DEFAULT_CONTEXT : context;
DBObject command = aggregation.toDbObject(collectionName, rootContext);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Executing aggregation: {}", serializeToJsonSafely(command));
}
CommandResult commandResult = executeCommand(command, this.readPreference);
handleCommandError(commandResult, command);
DBObject commandResult = new BatchAggregationLoader(this, queryMapper, mappingContext, readPreference,
Integer.MAX_VALUE)
.aggregate(collectionName, aggregation, context);
return new AggregationResults<O>(returnPotentiallyMappedResults(outputType, commandResult, collectionName),
commandResult);
@@ -1578,12 +1564,12 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
/**
* Returns the potentially mapped results of the given {@commandResult} contained some.
*
*
* @param outputType
* @param commandResult
* @return
*/
private <O> List<O> returnPotentiallyMappedResults(Class<O> outputType, CommandResult commandResult,
private <O> List<O> returnPotentiallyMappedResults(Class<O> outputType, DBObject commandResult,
String collectionName) {
@SuppressWarnings("unchecked")
@@ -1690,7 +1676,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
/**
* Create the specified collection using the provided options
*
*
* @param collectionName
* @param collectionOptions
* @return the collection that was created
@@ -1711,7 +1697,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
/**
* Map the results of an ad-hoc query on the default MongoDB collection to an object using the template's converter.
* The query document is specified as a standard {@link DBObject} and so is the fields specification.
*
*
* @param collectionName name of the collection to retrieve the objects from.
* @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.
@@ -1736,7 +1722,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
/**
* Map the results of an ad-hoc query on the default MongoDB collection to a List using the template's converter. The
* query document is specified as a standard DBObject and so is the fields specification.
*
*
* @param collectionName name of the collection to retrieve the objects from
* @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
@@ -1752,7 +1738,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
* Map the results of an ad-hoc query on the default MongoDB collection to a List of the specified type. The object is
* converted from the MongoDB native representation using an instance of {@see MongoConverter}. The query document is
* specified as a standard DBObject and so is the fields specification.
*
*
* @param collectionName name of the collection to retrieve the objects from.
* @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.
@@ -1805,7 +1791,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
* The first document that matches the query is returned and also removed from the collection in the database.
* <p/>
* The query document is specified as a standard DBObject and so is the fields specification.
*
*
* @param collectionName name of the collection to retrieve the objects from
* @param query the query document that specifies the criteria used to find a record
* @param entityClass the parameterized type of the returned list.
@@ -1856,7 +1842,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
/**
* Populates the id property of the saved object, if it's not set already.
*
*
* @param savedObject
* @param id
*/
@@ -1906,7 +1892,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
* <li>Execute the given {@link ConnectionCallback} for a {@link DBObject}.</li>
* <li>Apply the given {@link DbObjectCallback} to each of the {@link DBObject}s to obtain the result.</li>
* <ol>
*
*
* @param <T>
* @param collectionCallback the callback to retrieve the {@link DBObject} with
* @param objectCallback the {@link DbObjectCallback} to transform {@link DBObject}s into the actual domain type
@@ -1935,7 +1921,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
* <li>Iterate over the {@link DBCursor} and applies the given {@link DbObjectCallback} to each of the
* {@link DBObject}s collecting the actual result {@link List}.</li>
* <ol>
*
*
* @param <T>
* @param collectionCallback the callback to retrieve the {@link DBCursor} with
* @param preparer the {@link CursorPreparer} to potentially modify the {@link DBCursor} before ireating over it
@@ -2042,7 +2028,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
/**
* Handles {@link WriteResult} errors based on the configured {@link WriteResultChecking}.
*
*
* @param writeResult
* @param query
* @param operation
@@ -2086,11 +2072,11 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
/**
* Inspects the given {@link CommandResult} for erros and potentially throws an
* {@link InvalidDataAccessApiUsageException} for that error.
*
*
* @param result must not be {@literal null}.
* @param source must not be {@literal null}.
*/
private void handleCommandError(CommandResult result, DBObject source) {
private static void handleCommandError(CommandResult result, DBObject source) {
try {
result.throwOnError();
@@ -2107,8 +2093,16 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
private static final MongoConverter getDefaultMongoConverter(MongoDbFactory factory) {
DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory);
MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, new MongoMappingContext());
CustomConversions conversions = new CustomConversions(Collections.emptyList());
MongoMappingContext mappingContext = new MongoMappingContext();
mappingContext.setSimpleTypeHolder(conversions.getSimpleTypeHolder());
mappingContext.afterPropertiesSet();
MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, mappingContext);
converter.setCustomConversions(conversions);
converter.afterPropertiesSet();
return converter;
}
@@ -2124,7 +2118,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
/**
* 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.
*
*
* @param ex the exception to translate
* @param exceptionTranslator the {@link PersistenceExceptionTranslator} to be used for translation
* @return
@@ -2139,7 +2133,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
* Returns all identifiers for the given documents. Will augment the given identifiers and fill in only the ones that
* are {@literal null} currently. This would've been better solved in {@link #insertDBObjectList(String, List)}
* directly but would require a signature change of that method.
*
*
* @param ids
* @param documents
* @return TODO: Remove for 2.0 and change method signature of {@link #insertDBObjectList(String, List)}.
@@ -2162,7 +2156,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
/**
* Simple {@link CollectionCallback} that takes a query {@link DBObject} plus an optional fields specification
* {@link DBObject} and executes that against the {@link DBCollection}.
*
*
* @author Oliver Gierke
* @author Thomas Risberg
*/
@@ -2196,7 +2190,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
/**
* Simple {@link CollectionCallback} that takes a query {@link DBObject} plus an optional fields specification
* {@link DBObject} and executes that against the {@link DBCollection}.
*
*
* @author Oliver Gierke
* @author Thomas Risberg
*/
@@ -2227,7 +2221,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
/**
* Simple {@link CollectionCallback} that takes a query {@link DBObject} plus an optional fields specification
* {@link DBObject} and executes that against the {@link DBCollection}.
*
*
* @author Thomas Risberg
*/
private static class FindAndRemoveCallback implements CollectionCallback<DBObject> {
@@ -2272,7 +2266,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
/**
* Simple internal callback to allow operations on a {@link DBObject}.
*
*
* @author Oliver Gierke
* @author Thomas Darimont
*/
@@ -2285,7 +2279,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
/**
* Simple {@link DbObjectCallback} that will transform {@link DBObject} into the given target type using the given
* {@link MongoReader}.
*
*
* @author Oliver Gierke
* @author Christoph Strobl
*/
@@ -2297,8 +2291,9 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
public ReadDbObjectCallback(EntityReader<? super T, DBObject> reader, Class<T> type, String collectionName) {
Assert.notNull(reader);
Assert.notNull(type);
Assert.notNull(reader, "EntityReader must not be null!");
Assert.notNull(type, "Entity type must not be null!");
this.reader = reader;
this.type = type;
this.collectionName = collectionName;
@@ -2431,7 +2426,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
/**
* {@link DbObjectCallback} that assumes a {@link GeoResult} to be created, delegates actual content unmarshalling to
* a delegate and creates a {@link GeoResult} from the result.
*
*
* @author Oliver Gierke
*/
static class GeoNearResultDbObjectCallback<T> implements DbObjectCallback<GeoResult<T>> {
@@ -2442,11 +2437,13 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
/**
* Creates a new {@link GeoNearResultDbObjectCallback} using the given {@link DbObjectCallback} delegate for
* {@link GeoResult} content unmarshalling.
*
*
* @param delegate must not be {@literal null}.
*/
public GeoNearResultDbObjectCallback(DbObjectCallback<T> delegate, Metric metric) {
Assert.notNull(delegate);
Assert.notNull(delegate, "DocumentCallback must not be null!");
this.delegate = delegate;
this.metric = metric;
}
@@ -2464,7 +2461,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
/**
* A {@link CloseableIterator} that is backed by a MongoDB {@link Cursor}.
*
*
* @since 1.7
* @author Thomas Darimont
*/
@@ -2476,7 +2473,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
/**
* Creates a new {@link CloseableIterableCursorAdapter} backed by the given {@link Cursor}.
*
*
* @param cursor
* @param exceptionTranslator
* @param objectReadCallback
@@ -2524,7 +2521,11 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
Cursor c = cursor;
try {
c.close();
if (c != null) {
c.close();
}
} catch (RuntimeException ex) {
throw potentiallyConvertRuntimeException(ex, exceptionTranslator);
} finally {
@@ -2534,4 +2535,156 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
}
}
}
/**
* {@link BatchAggregationLoader} is a little helper that can process cursor results returned by an aggregation
* command execution. On presence of a {@literal nextBatch} indicated by presence of an {@code id} field in the
* {@code cursor} another {@code getMore} command gets executed reading the next batch of documents until all results
* are loaded.
*
* @author Christoph Strobl
* @since 1.10
*/
static class BatchAggregationLoader {
private static final String CURSOR_FIELD = "cursor";
private static final String RESULT_FIELD = "result";
private static final String BATCH_SIZE_FIELD = "batchSize";
private static final String FIRST_BATCH = "firstBatch";
private static final String NEXT_BATCH = "nextBatch";
private static final String SERVER_USED = "serverUsed";
private static final String OK = "ok";
private final MongoTemplate template;
private final QueryMapper queryMapper;
private final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
private final ReadPreference readPreference;
private final int batchSize;
BatchAggregationLoader(MongoTemplate template, QueryMapper queryMapper,
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext,
ReadPreference readPreference, int batchSize) {
this.template = template;
this.queryMapper = queryMapper;
this.mappingContext = mappingContext;
this.readPreference = readPreference;
this.batchSize = batchSize;
}
/**
* Run aggregation command and fetch all results.
*/
DBObject aggregate(String collectionName, Aggregation aggregation, AggregationOperationContext context) {
DBObject command = prepareAggregationCommand(collectionName, aggregation, context, batchSize);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Executing aggregation: {}", serializeToJsonSafely(command));
}
return mergeAggregationResults(aggregateBatched(command, collectionName, batchSize));
}
/**
* Pre process the aggregation command sent to the server by adding {@code cursor} options to match execution on
* different server versions.
*/
private DBObject prepareAggregationCommand(String collectionName, Aggregation aggregation,
AggregationOperationContext context, int batchSize) {
AggregationUtil aggregationUtil = new AggregationUtil(queryMapper, mappingContext);
AggregationOperationContext rootContext = aggregationUtil.prepareAggregationContext(aggregation, context);
DBObject command = aggregationUtil.createCommand(collectionName, aggregation, rootContext);
if (!aggregation.getOptions().isExplain()) {
command.put(CURSOR_FIELD, new BasicDBObject(BATCH_SIZE_FIELD, batchSize));
}
return command;
}
private List<DBObject> aggregateBatched(DBObject command, String collectionName, int batchSize) {
List<DBObject> results = new ArrayList<DBObject>();
CommandResult commandResult = template.executeCommand(command, readPreference);
results.add(postProcessResult(command, commandResult));
while (hasNext(commandResult)) {
DBObject getMore = new BasicDBObject("getMore", getNextBatchId(commandResult)) //
.append("collection", collectionName) //
.append(BATCH_SIZE_FIELD, batchSize);
commandResult = template.executeCommand(getMore, this.readPreference);
results.add(postProcessResult(command, commandResult));
}
return results;
}
private static DBObject postProcessResult(DBObject command, CommandResult commandResult) {
handleCommandError(commandResult, command);
if (!commandResult.containsField(CURSOR_FIELD)) {
return commandResult;
}
DBObject resultObject = new BasicDBObject(SERVER_USED, commandResult.get(SERVER_USED));
resultObject.put(OK, commandResult.get(OK));
DBObject cursor = (DBObject) commandResult.get(CURSOR_FIELD);
if (cursor.containsField(FIRST_BATCH)) {
resultObject.put(RESULT_FIELD, cursor.get(FIRST_BATCH));
} else {
resultObject.put(RESULT_FIELD, cursor.get(NEXT_BATCH));
}
return resultObject;
}
private static DBObject mergeAggregationResults(List<DBObject> batchResults) {
if (batchResults.size() == 1) {
return batchResults.iterator().next();
}
DBObject commandResult = new BasicDBObject(3);
List<Object> allResults = new ArrayList<Object>();
for (DBObject batchResult : batchResults) {
Collection documents = (Collection<?>) batchResult.get(RESULT_FIELD);
if (!CollectionUtils.isEmpty(documents)) {
allResults.addAll(documents);
}
}
// take general info from first batch
commandResult.put(SERVER_USED, batchResults.iterator().next().get(SERVER_USED));
commandResult.put(OK, batchResults.iterator().next().get(OK));
// and append the merged batchResults
commandResult.put(RESULT_FIELD, allResults);
return commandResult;
}
private static boolean hasNext(DBObject commandResult) {
if (!commandResult.containsField(CURSOR_FIELD)) {
return false;
}
Object next = getNextBatchId(commandResult);
return next != null && ((Number) next).longValue() != 0L;
}
private static Object getNextBatchId(DBObject commandResult) {
return ((DBObject) commandResult.get(CURSOR_FIELD)).get("id");
}
}
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2015 the original author or authors.
* Copyright 2015-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
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2015 the original author or authors.
* Copyright 2015-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
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2015 the original author or authors.
* Copyright 2015-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
* 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,

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2015 the original author or authors.
* Copyright 2015-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
* 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,

Some files were not shown because too many files have changed in this diff Show More