Compare commits
389 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fbec97fcd6 | ||
|
|
90a6f657e5 | ||
|
|
180f34f1e4 | ||
|
|
6ad5e3ad18 | ||
|
|
618c274e59 | ||
|
|
795e507b25 | ||
|
|
64cfaf6a4f | ||
|
|
43224ccec7 | ||
|
|
54ef3305ae | ||
|
|
fa2dbf13a9 | ||
|
|
7c215a9ebf | ||
|
|
c9287a2465 | ||
|
|
5f070ee9de | ||
|
|
0b963fd9c6 | ||
|
|
29849dcd13 | ||
|
|
27dc8bcade | ||
|
|
fe4597f0e6 | ||
|
|
902ea24ded | ||
|
|
2e12f3a22e | ||
|
|
ebc22c8d32 | ||
|
|
9e01c4aad5 | ||
|
|
bd2b2653c3 | ||
|
|
fb3655329b | ||
|
|
a5cefddbcc | ||
|
|
fe3f358480 | ||
|
|
d7a63ac882 | ||
|
|
526037e71b | ||
|
|
2ba6f48335 | ||
|
|
ed22672b5c | ||
|
|
7c94718c9b | ||
|
|
d56d84924a | ||
|
|
034d3f4d43 | ||
|
|
c9a6a04fc3 | ||
|
|
fb8fd05cf0 | ||
|
|
8c62077d08 | ||
|
|
23967107f2 | ||
|
|
704a9658a7 | ||
|
|
a394d1ea8e | ||
|
|
b35e2e8eb8 | ||
|
|
26cda42892 | ||
|
|
145fc27bd9 | ||
|
|
57b541ac86 | ||
|
|
a21a539c83 | ||
|
|
89fef9306f | ||
|
|
b2b67270d1 | ||
|
|
4d72b0b78f | ||
|
|
cd510d97bd | ||
|
|
bbcaf361c6 | ||
|
|
4cf922a05b | ||
|
|
da07d9e3f8 | ||
|
|
e0b0763349 | ||
|
|
00ca50cf17 | ||
|
|
3a461d2bc6 | ||
|
|
df3f91fff4 | ||
|
|
5d75c2a921 | ||
|
|
d723784925 | ||
|
|
a2426ec98d | ||
|
|
568f6bb1e0 | ||
|
|
c2f94cb840 | ||
|
|
14981872e6 | ||
|
|
624ec3ce55 | ||
|
|
db9d282313 | ||
|
|
10972bfda1 | ||
|
|
28454cb554 | ||
|
|
f17c4923e6 | ||
|
|
4414771aaa | ||
|
|
9acc558ae9 | ||
|
|
2d946a2c9a | ||
|
|
715a2d3da4 | ||
|
|
01c1ec2e5b | ||
|
|
7596f37235 | ||
|
|
da4ccaa975 | ||
|
|
aed9b4d0da | ||
|
|
54a0e34049 | ||
|
|
6cb8055601 | ||
|
|
34829fca84 | ||
|
|
94b2495145 | ||
|
|
f2301eaf5b | ||
|
|
e3e201edb9 | ||
|
|
c738148b40 | ||
|
|
ec5268a862 | ||
|
|
9bc073501f | ||
|
|
3d00ef1076 | ||
|
|
a07ca615be | ||
|
|
15501f0424 | ||
|
|
8d0edcd389 | ||
|
|
02241870d7 | ||
|
|
d76dd90325 | ||
|
|
cc8c3448a8 | ||
|
|
3981a8ac92 | ||
|
|
b9d72060af | ||
|
|
c1647ed269 | ||
|
|
9faeb1afe0 | ||
|
|
bbc7a64956 | ||
|
|
5f32339175 | ||
|
|
013f56d141 | ||
|
|
ff9217b33e | ||
|
|
a87476f474 | ||
|
|
df40a4820e | ||
|
|
ac0aed8449 | ||
|
|
488462d5b3 | ||
|
|
639fecc9ca | ||
|
|
47f9e3c739 | ||
|
|
25507b995f | ||
|
|
1e29687135 | ||
|
|
d594ae1bd0 | ||
|
|
441e7fbb39 | ||
|
|
b9389860ce | ||
|
|
58426e0314 | ||
|
|
209466a85e | ||
|
|
7c18b7dc0f | ||
|
|
3ff0975ab9 | ||
|
|
ee9d8768a2 | ||
|
|
b77658e188 | ||
|
|
0cb0cb700b | ||
|
|
364920e644 | ||
|
|
0495dd89ce | ||
|
|
19ccdd473a | ||
|
|
8fecc92dd4 | ||
|
|
7fbb6583a5 | ||
|
|
46550f6830 | ||
|
|
f076f75866 | ||
|
|
d9bf13cc1e | ||
|
|
626dfa4f9a | ||
|
|
26c12214d3 | ||
|
|
f82b791f72 | ||
|
|
3785a52676 | ||
|
|
41897c7d46 | ||
|
|
f3397e95bc | ||
|
|
5807c5d8bc | ||
|
|
70783d5806 | ||
|
|
02e3fa1486 | ||
|
|
f09c956ab2 | ||
|
|
6d6201d327 | ||
|
|
5217e7a7e0 | ||
|
|
f56bb16a12 | ||
|
|
0869fdb5b8 | ||
|
|
59aa9f96cc | ||
|
|
944fabb87d | ||
|
|
3cf2cd2d59 | ||
|
|
44a4e65a72 | ||
|
|
e378b6f4a6 | ||
|
|
61667bde17 | ||
|
|
4148e38ca9 | ||
|
|
e8d3c9e932 | ||
|
|
fdc8ad8580 | ||
|
|
e7cc9231ed | ||
|
|
2d2953cbc5 | ||
|
|
4dab0369ed | ||
|
|
8ad0dc87e3 | ||
|
|
16ad3c614f | ||
|
|
2663428825 | ||
|
|
f5d5a813f3 | ||
|
|
b69ddd43ac | ||
|
|
9f3dca3be9 | ||
|
|
49e97b7f47 | ||
|
|
7775746d26 | ||
|
|
67bae7c813 | ||
|
|
038ab7d8bc | ||
|
|
0ac6956807 | ||
|
|
b1ec25d9be | ||
|
|
0a609d1ac9 | ||
|
|
e4103eacda | ||
|
|
bf58e9536b | ||
|
|
5fe67339e1 | ||
|
|
32a2970e76 | ||
|
|
e8c9ac7dd0 | ||
|
|
29b4a9dcc3 | ||
|
|
7275a10c1e | ||
|
|
61b5977ada | ||
|
|
9ff3888a21 | ||
|
|
72f461ae30 | ||
|
|
2af322a823 | ||
|
|
3694761f92 | ||
|
|
c3b0e81db2 | ||
|
|
27e68de5aa | ||
|
|
04ace43046 | ||
|
|
65996f3ad8 | ||
|
|
237eace8e4 | ||
|
|
0b31621d35 | ||
|
|
3f009053fe | ||
|
|
a2d470cd23 | ||
|
|
9525cdedfc | ||
|
|
867fcf6df2 | ||
|
|
3ddac744ce | ||
|
|
e565d25084 | ||
|
|
27623fce01 | ||
|
|
c9d471e5d5 | ||
|
|
6641277aaa | ||
|
|
29eba6e427 | ||
|
|
d10e4afefd | ||
|
|
14bb4b586f | ||
|
|
d795836994 | ||
|
|
d216fed8db | ||
|
|
26b7267737 | ||
|
|
69d749d028 | ||
|
|
946617f634 | ||
|
|
50bb03004f | ||
|
|
2f68d8c85d | ||
|
|
ebfbc4e9d0 | ||
|
|
b96707a0e2 | ||
|
|
7523eedd8d | ||
|
|
ae8df6b705 | ||
|
|
72a0a5623a | ||
|
|
5f8f858d89 | ||
|
|
8db4feeef0 | ||
|
|
b9a392168d | ||
|
|
479dc3a0d6 | ||
|
|
59ebbd3d35 | ||
|
|
38556f522f | ||
|
|
166304849a | ||
|
|
f71b38b731 | ||
|
|
c4af78d81d | ||
|
|
a281ec83b5 | ||
|
|
407087b3a7 | ||
|
|
90411decce | ||
|
|
71135395c1 | ||
|
|
9c43ece3a7 | ||
|
|
283bfce2fe | ||
|
|
42cc6ff37f | ||
|
|
9ded78b13c | ||
|
|
b0842a89fd | ||
|
|
5a9eef7c96 | ||
|
|
77425736e9 | ||
|
|
6aa8f84428 | ||
|
|
b83f2e9198 | ||
|
|
2171c814e8 | ||
|
|
d0e398a39c | ||
|
|
428c60dee0 | ||
|
|
80393b2dc2 | ||
|
|
c15a542863 | ||
|
|
92c6db13dc | ||
|
|
1681bcd15b | ||
|
|
1f2d0da5ed | ||
|
|
8009bd2846 | ||
|
|
cbd9807f16 | ||
|
|
f672b17dfc | ||
|
|
2a018b04ec | ||
|
|
8e748ab1c2 | ||
|
|
49f9307884 | ||
|
|
ebd8491642 | ||
|
|
f581677bf2 | ||
|
|
a2a172e559 | ||
|
|
61fd09bb43 | ||
|
|
4b11d415f1 | ||
|
|
beabbc0307 | ||
|
|
ad55a8bab7 | ||
|
|
79e0b44b5e | ||
|
|
b747e226d7 | ||
|
|
0bdd4a2eb4 | ||
|
|
dda91f9d48 | ||
|
|
d32afee0e0 | ||
|
|
5e4cced3e6 | ||
|
|
375d59f7a2 | ||
|
|
0fe197d608 | ||
|
|
5325e46aaa | ||
|
|
1fe5793bd7 | ||
|
|
909a0bb2f2 | ||
|
|
c3983a4a32 | ||
|
|
94cd8fd827 | ||
|
|
34ca906b80 | ||
|
|
0a9f7d0e30 | ||
|
|
36af892679 | ||
|
|
12f3dce709 | ||
|
|
ae3b4be772 | ||
|
|
4f813ae7a7 | ||
|
|
bd92f67e54 | ||
|
|
63968513d9 | ||
|
|
2b0026931a | ||
|
|
0df5e6ba58 | ||
|
|
2a0a880f57 | ||
|
|
d920cee5e7 | ||
|
|
3af2d810bc | ||
|
|
a4c754467e | ||
|
|
0ab635d7ee | ||
|
|
ef46edc941 | ||
|
|
93f81f7321 | ||
|
|
f42c24a605 | ||
|
|
1ac88e44a1 | ||
|
|
324f656410 | ||
|
|
265ad423e5 | ||
|
|
0a4310760c | ||
|
|
38ce0a24cc | ||
|
|
fb835e6a29 | ||
|
|
c77025859b | ||
|
|
61cb23db5c | ||
|
|
6f138e641b | ||
|
|
5925b5133c | ||
|
|
9d4f34a6ff | ||
|
|
85ff5a7254 | ||
|
|
593c5366fa | ||
|
|
9c06124943 | ||
|
|
e342008c4b | ||
|
|
a4782ae9ec | ||
|
|
4cc52dc1e1 | ||
|
|
e41e072217 | ||
|
|
d199a40664 | ||
|
|
25d29a2332 | ||
|
|
b19816490f | ||
|
|
d5fec0989c | ||
|
|
52b52dba93 | ||
|
|
d046f30862 | ||
|
|
7413a031c1 | ||
|
|
8e3d7f96c4 | ||
|
|
d2d162dee6 | ||
|
|
b9aa410ac1 | ||
|
|
6f278ce838 | ||
|
|
3ed72a922a | ||
|
|
98b3c1678f | ||
|
|
45818f26b3 | ||
|
|
822e29524d | ||
|
|
3476c639c2 | ||
|
|
35fa922daa | ||
|
|
8f7ea3a2ed | ||
|
|
7ab7212edc | ||
|
|
27651ef0be | ||
|
|
174f7f0886 | ||
|
|
437bf89533 | ||
|
|
c3e5fca73d | ||
|
|
8340c02d9a | ||
|
|
3c6db34870 | ||
|
|
9f3319928b | ||
|
|
97a03d824a | ||
|
|
8149273df9 | ||
|
|
e838662536 | ||
|
|
e784e58a0a | ||
|
|
fda72d6eb2 | ||
|
|
a96752da80 | ||
|
|
320a28740a | ||
|
|
e55e748cfd | ||
|
|
737f7b4f30 | ||
|
|
408c5d8684 | ||
|
|
982adf317e | ||
|
|
7914e8a630 | ||
|
|
dc4a30a7f8 | ||
|
|
29e405b800 | ||
|
|
1a105333aa | ||
|
|
14e326dc09 | ||
|
|
f026ab419d | ||
|
|
75139042e0 | ||
|
|
6236384c1d | ||
|
|
6993054d6a | ||
|
|
35bfb92ace | ||
|
|
89a02bb822 | ||
|
|
c9c5fe62ca | ||
|
|
d250f88c38 | ||
|
|
bcb63b2732 | ||
|
|
2c4377c9a6 | ||
|
|
e992d813fb | ||
|
|
aa1e91c761 | ||
|
|
9737464f9a | ||
|
|
204a0515c4 | ||
|
|
c6dae3c444 | ||
|
|
c1c7daf0ed | ||
|
|
14678ce7a9 | ||
|
|
4e56d9c575 | ||
|
|
cab35759db | ||
|
|
7b49b120e3 | ||
|
|
dc57b66adf | ||
|
|
0449719a16 | ||
|
|
3d8b6868c7 | ||
|
|
68db0d4cb0 | ||
|
|
c9dfeea0c7 | ||
|
|
1a11877ae9 | ||
|
|
ea4782c421 | ||
|
|
a0ac3510a0 | ||
|
|
192399413d | ||
|
|
a0be890437 | ||
|
|
438dbc4b33 | ||
|
|
407affb458 | ||
|
|
c6a4e7166c | ||
|
|
7f39c42eb7 | ||
|
|
40da4701de | ||
|
|
3ae6aebebb | ||
|
|
bbfa0f7b83 | ||
|
|
63d6234446 | ||
|
|
9ff86feb4f | ||
|
|
8c838e8350 | ||
|
|
a79930145d | ||
|
|
9059a77712 | ||
|
|
a741400e9b | ||
|
|
b786b8220a | ||
|
|
710770e88d | ||
|
|
e631e2d7c5 | ||
|
|
3dc1e9355a | ||
|
|
2985b4ca3d | ||
|
|
578441ee9f | ||
|
|
36838ffe31 | ||
|
|
5bd0e21173 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -15,4 +15,3 @@ src/ant/.ant-targets-upload-dist.xml
|
|||||||
atlassian-ide-plugin.xml
|
atlassian-ide-plugin.xml
|
||||||
/.gradle/
|
/.gradle/
|
||||||
/.idea/
|
/.idea/
|
||||||
*.graphml
|
|
||||||
110
.mvn/wrapper/MavenWrapperDownloader.java
vendored
110
.mvn/wrapper/MavenWrapperDownloader.java
vendored
@@ -1,110 +0,0 @@
|
|||||||
/*
|
|
||||||
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
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.net.*;
|
|
||||||
import java.io.*;
|
|
||||||
import java.nio.channels.*;
|
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
public class MavenWrapperDownloader {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
|
|
||||||
*/
|
|
||||||
private static final String DEFAULT_DOWNLOAD_URL =
|
|
||||||
"https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
|
|
||||||
* use instead of the default one.
|
|
||||||
*/
|
|
||||||
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
|
|
||||||
".mvn/wrapper/maven-wrapper.properties";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Path where the maven-wrapper.jar will be saved to.
|
|
||||||
*/
|
|
||||||
private static final String MAVEN_WRAPPER_JAR_PATH =
|
|
||||||
".mvn/wrapper/maven-wrapper.jar";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Name of the property which should be used to override the default download url for the wrapper.
|
|
||||||
*/
|
|
||||||
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
|
|
||||||
|
|
||||||
public static void main(String args[]) {
|
|
||||||
System.out.println("- Downloader started");
|
|
||||||
File baseDirectory = new File(args[0]);
|
|
||||||
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
|
|
||||||
|
|
||||||
// If the maven-wrapper.properties exists, read it and check if it contains a custom
|
|
||||||
// wrapperUrl parameter.
|
|
||||||
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
|
|
||||||
String url = DEFAULT_DOWNLOAD_URL;
|
|
||||||
if(mavenWrapperPropertyFile.exists()) {
|
|
||||||
FileInputStream mavenWrapperPropertyFileInputStream = null;
|
|
||||||
try {
|
|
||||||
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
|
|
||||||
Properties mavenWrapperProperties = new Properties();
|
|
||||||
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
|
|
||||||
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
|
|
||||||
} catch (IOException e) {
|
|
||||||
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
if(mavenWrapperPropertyFileInputStream != null) {
|
|
||||||
mavenWrapperPropertyFileInputStream.close();
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
// Ignore ...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
System.out.println("- Downloading from: : " + url);
|
|
||||||
|
|
||||||
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
|
|
||||||
if(!outputFile.getParentFile().exists()) {
|
|
||||||
if(!outputFile.getParentFile().mkdirs()) {
|
|
||||||
System.out.println(
|
|
||||||
"- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
|
|
||||||
try {
|
|
||||||
downloadFileFromURL(url, outputFile);
|
|
||||||
System.out.println("Done");
|
|
||||||
System.exit(0);
|
|
||||||
} catch (Throwable e) {
|
|
||||||
System.out.println("- Error downloading");
|
|
||||||
e.printStackTrace();
|
|
||||||
System.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
|
|
||||||
URL website = new URL(urlString);
|
|
||||||
ReadableByteChannel rbc;
|
|
||||||
rbc = Channels.newChannel(website.openStream());
|
|
||||||
FileOutputStream fos = new FileOutputStream(destination);
|
|
||||||
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
|
|
||||||
fos.close();
|
|
||||||
rbc.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
35
.travis.yml
35
.travis.yml
@@ -1,35 +0,0 @@
|
|||||||
language: java
|
|
||||||
|
|
||||||
jdk:
|
|
||||||
- oraclejdk8
|
|
||||||
|
|
||||||
before_install:
|
|
||||||
- mkdir -p downloads
|
|
||||||
- mkdir -p var/db var/log
|
|
||||||
- if [[ ! -d downloads/mongodb-linux-x86_64-ubuntu1604-${MONGO_VERSION} ]] ; then cd downloads && wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu1604-${MONGO_VERSION}.tgz && tar xzf mongodb-linux-x86_64-ubuntu1604-${MONGO_VERSION}.tgz && cd ..; fi
|
|
||||||
- downloads/mongodb-linux-x86_64-ubuntu1604-${MONGO_VERSION}/bin/mongod --version
|
|
||||||
- downloads/mongodb-linux-x86_64-ubuntu1604-${MONGO_VERSION}/bin/mongod --dbpath var/db --replSet rs0 --fork --logpath var/log/mongod.log
|
|
||||||
- sleep 10
|
|
||||||
- |-
|
|
||||||
downloads/mongodb-linux-x86_64-ubuntu1604-${MONGO_VERSION}/bin/mongo --eval "rs.initiate({_id: 'rs0', members:[{_id: 0, host: '127.0.0.1:27017'}]});"
|
|
||||||
sleep 15
|
|
||||||
|
|
||||||
env:
|
|
||||||
matrix:
|
|
||||||
- PROFILE=ci
|
|
||||||
global:
|
|
||||||
- MONGO_VERSION=4.0.0
|
|
||||||
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
- oracle-java8-installer
|
|
||||||
|
|
||||||
sudo: false
|
|
||||||
|
|
||||||
cache:
|
|
||||||
directories:
|
|
||||||
- $HOME/.m2
|
|
||||||
- downloads
|
|
||||||
|
|
||||||
script: "mvn clean dependency:list test -P${PROFILE} -Dsort"
|
|
||||||
43
CI.adoc
Normal file
43
CI.adoc
Normal 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
123
Jenkinsfile
vendored
Normal 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
159
README.adoc
Normal 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? We’d 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 doesn’t 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 don’t 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[Contributor’s 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].
|
||||||
186
README.md
186
README.md
@@ -1,186 +0,0 @@
|
|||||||
[](http://projects.spring.io/spring-data-mongodb#quick-start)
|
|
||||||
[](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 MongoClient mongoClient() 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*");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### MongoDB 4.0 Transactions
|
|
||||||
|
|
||||||
As of version 4 MongoDB supports [Transactions](https://www.mongodb.com/transactions). Transactions are built on top of
|
|
||||||
`ClientSessions` and therefore require an active session.
|
|
||||||
|
|
||||||
`MongoTransactionManager` is the gateway to the well known Spring transaction support. It allows applications to use
|
|
||||||
[managed transaction features of Spring](http://docs.spring.io/spring/docs/current/spring-framework-reference/html/transaction.html).
|
|
||||||
The `MongoTransactionManager` binds a `ClientSession` to the thread. `MongoTemplate` automatically detects those and operates on them accordingly.
|
|
||||||
|
|
||||||
```java
|
|
||||||
@Configuration
|
|
||||||
static class Config extends AbstractMongoConfiguration {
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
MongoTransactionManager transactionManager(MongoDbFactory dbFactory) {
|
|
||||||
return new MongoTransactionManager(dbFactory);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component
|
|
||||||
public class StateService {
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
void someBusinessFunction(Step step) {
|
|
||||||
|
|
||||||
template.insert(step);
|
|
||||||
|
|
||||||
process(step);
|
|
||||||
|
|
||||||
template.update(Step.class).apply(Update.set("state", // ...
|
|
||||||
};
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
## 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.spring.io/browse/DATAMONGO) 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 License Agreement](https://cla.pivotal.io/sign/spring). 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. If you forget to do so, you'll be reminded when you submit a pull request. Active contributors might be asked to join the core team, and given the ability to merge pull requests.
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
FROM openjdk:11-jdk
|
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y apt-transport-https
|
|
||||||
|
|
||||||
RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 9DA31620334BD75D9DCB49F368818C72E52529D4
|
|
||||||
|
|
||||||
RUN echo "deb http://repo.mongodb.org/apt/debian stretch/mongodb-org/4.0 main" | tee /etc/apt/sources.list.d/mongodb-org-4.0.list
|
|
||||||
|
|
||||||
RUN apt-get update
|
|
||||||
|
|
||||||
RUN apt-get install -y mongodb-org=4.0.3 mongodb-org-server=4.0.3 mongodb-org-shell=4.0.3 mongodb-org-mongos=4.0.3 mongodb-org-tools=4.0.3
|
|
||||||
|
|
||||||
RUN apt-get clean \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
FROM openjdk:8-jdk
|
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y apt-transport-https
|
|
||||||
|
|
||||||
RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 9DA31620334BD75D9DCB49F368818C72E52529D4
|
|
||||||
|
|
||||||
RUN echo "deb http://repo.mongodb.org/apt/debian stretch/mongodb-org/4.0 main" | tee /etc/apt/sources.list.d/mongodb-org-4.0.list
|
|
||||||
|
|
||||||
RUN apt-get update
|
|
||||||
|
|
||||||
RUN apt-get install -y mongodb-org=4.0.3 mongodb-org-server=4.0.3 mongodb-org-shell=4.0.3 mongodb-org-mongos=4.0.3 mongodb-org-tools=4.0.3
|
|
||||||
|
|
||||||
RUN apt-get clean \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
== Running CI tasks locally
|
|
||||||
|
|
||||||
Since Concourse is built on top of Docker, it's easy to:
|
|
||||||
|
|
||||||
* Debug what went wrong on your local machine.
|
|
||||||
* Test out a a tweak to your `test.sh` script 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 Concourse 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-8-jdk-with-mongodb /bin/bash`
|
|
||||||
+
|
|
||||||
This will launch the Docker image and mount your source code at `spring-data-mongodb-github`.
|
|
||||||
+
|
|
||||||
Next, run the `test.sh` script from inside the container:
|
|
||||||
+
|
|
||||||
2. `PROFILE=none spring-data-mongodb-github/ci/test.sh`
|
|
||||||
|
|
||||||
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 test the `build.sh` script, do this:
|
|
||||||
|
|
||||||
1. `mkdir /tmp/spring-data-mongodb-artifactory`
|
|
||||||
2. `docker run -it --mount type=bind,source="$(pwd)",target=/spring-data-mongodb-github --mount type=bind,source="/tmp/spring-data-mongodb-artifactory",target=/spring-data-mongodb-artifactory springci/spring-data-8-jdk-with-mongodb /bin/bash`
|
|
||||||
+
|
|
||||||
This will launch the Docker image and mount your source code at `spring-data-mongodb-github` and the temporary
|
|
||||||
artifactory output directory at `spring-data-mongodb-artifactory`.
|
|
||||||
+
|
|
||||||
Next, run the `build.sh` script from inside the container:
|
|
||||||
+
|
|
||||||
3. `spring-data-mongodb-github/ci/build.sh`
|
|
||||||
|
|
||||||
IMPORTANT: `build.sh` doesn't actually push to Artifactory so don't worry about accidentally deploying anything.
|
|
||||||
It just deploys to a local folder. That way, the `artifactory-resource` later in the pipeline can pick up these artifacts
|
|
||||||
and deliver them to artifactory.
|
|
||||||
|
|
||||||
NOTE: Docker containers can eat up disk space fast! From time to time, run `docker system prune` to clean out old images.
|
|
||||||
15
ci/build.sh
15
ci/build.sh
@@ -1,15 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
[[ -d $PWD/maven && ! -d $HOME/.m2 ]] && ln -s $PWD/maven $HOME/.m2
|
|
||||||
|
|
||||||
spring_data_mongodb_artifactory=$(pwd)/spring-data-mongodb-artifactory
|
|
||||||
|
|
||||||
rm -rf $HOME/.m2/repository/org/springframework/data 2> /dev/null || :
|
|
||||||
|
|
||||||
cd spring-data-mongodb-github
|
|
||||||
|
|
||||||
./mvnw deploy \
|
|
||||||
-Dmaven.test.skip=true \
|
|
||||||
-DaltDeploymentRepository=distribution::default::file://${spring_data_mongodb_artifactory} \
|
|
||||||
19
ci/build.yml
19
ci/build.yml
@@ -1,19 +0,0 @@
|
|||||||
---
|
|
||||||
platform: linux
|
|
||||||
|
|
||||||
image_resource:
|
|
||||||
type: docker-image
|
|
||||||
source:
|
|
||||||
repository: springci/spring-data-8-jdk-with-mongodb
|
|
||||||
|
|
||||||
inputs:
|
|
||||||
- name: spring-data-mongodb-github
|
|
||||||
|
|
||||||
outputs:
|
|
||||||
- name: spring-data-mongodb-artifactory
|
|
||||||
|
|
||||||
caches:
|
|
||||||
- path: maven
|
|
||||||
|
|
||||||
run:
|
|
||||||
path: spring-data-mongodb-github/ci/build.sh
|
|
||||||
14
ci/openjdk8-mongodb-4.0/Dockerfile
Normal file
14
ci/openjdk8-mongodb-4.0/Dockerfile
Normal 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/*
|
||||||
14
ci/openjdk8-mongodb-4.1/Dockerfile
Normal file
14
ci/openjdk8-mongodb-4.1/Dockerfile
Normal 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/*
|
||||||
14
ci/test.sh
14
ci/test.sh
@@ -1,14 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
mkdir -p /data/db
|
|
||||||
mongod &
|
|
||||||
|
|
||||||
[[ -d $PWD/maven && ! -d $HOME/.m2 ]] && ln -s $PWD/maven $HOME/.m2
|
|
||||||
|
|
||||||
rm -rf $HOME/.m2/repository/org/springframework/data/mongodb 2> /dev/null || :
|
|
||||||
|
|
||||||
cd spring-data-mongodb-github
|
|
||||||
|
|
||||||
./mvnw clean dependency:list test -P${PROFILE} -Dsort
|
|
||||||
16
ci/test.yml
16
ci/test.yml
@@ -1,16 +0,0 @@
|
|||||||
---
|
|
||||||
platform: linux
|
|
||||||
|
|
||||||
image_resource:
|
|
||||||
type: docker-image
|
|
||||||
source:
|
|
||||||
repository: springci/spring-data-8-jdk-with-mongodb
|
|
||||||
|
|
||||||
inputs:
|
|
||||||
- name: spring-data-mongodb-github
|
|
||||||
|
|
||||||
caches:
|
|
||||||
- path: maven
|
|
||||||
|
|
||||||
run:
|
|
||||||
path: spring-data-mongodb-github/ci/test.sh
|
|
||||||
291
etc/formatting.xml
Normal file
291
etc/formatting.xml
Normal file
@@ -0,0 +1,291 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<profiles version="12">
|
||||||
|
<profile kind="CodeFormatterProfile" name="Spring Data" version="12">
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.compiler.source" value="1.7"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="2"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="tab"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="2"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.7"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="120"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.7"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
2
mvnw
vendored
2
mvnw
vendored
@@ -8,7 +8,7 @@
|
|||||||
# "License"); you may not use this file except in compliance
|
# "License"); you may not use this file except in compliance
|
||||||
# with the License. You may obtain a copy of the License at
|
# 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,
|
# Unless required by applicable law or agreed to in writing,
|
||||||
# software distributed under the License is distributed on an
|
# software distributed under the License is distributed on an
|
||||||
|
|||||||
2
mvnw.cmd
vendored
2
mvnw.cmd
vendored
@@ -7,7 +7,7 @@
|
|||||||
@REM "License"); you may not use this file except in compliance
|
@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 with the License. You may obtain a copy of the License at
|
||||||
@REM
|
@REM
|
||||||
@REM http://www.apache.org/licenses/LICENSE-2.0
|
@REM https://www.apache.org/licenses/LICENSE-2.0
|
||||||
@REM
|
@REM
|
||||||
@REM Unless required by applicable law or agreed to in writing,
|
@REM Unless required by applicable law or agreed to in writing,
|
||||||
@REM software distributed under the License is distributed on an
|
@REM software distributed under the License is distributed on an
|
||||||
|
|||||||
155
pom.xml
155
pom.xml
@@ -1,35 +1,36 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?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>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<groupId>org.springframework.data</groupId>
|
<groupId>org.springframework.data</groupId>
|
||||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||||
<version>2.2.0.M2</version>
|
<version>1.10.24.BUILD-SNAPSHOT</version>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
<name>Spring Data MongoDB</name>
|
<name>Spring Data MongoDB</name>
|
||||||
<description>MongoDB support for Spring Data</description>
|
<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>
|
<parent>
|
||||||
<groupId>org.springframework.data.build</groupId>
|
<groupId>org.springframework.data.build</groupId>
|
||||||
<artifactId>spring-data-parent</artifactId>
|
<artifactId>spring-data-parent</artifactId>
|
||||||
<version>2.2.0.M2</version>
|
<version>1.9.24.BUILD-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
<module>spring-data-mongodb</module>
|
<module>spring-data-mongodb</module>
|
||||||
<module>spring-data-mongodb-cross-store</module>
|
<module>spring-data-mongodb-cross-store</module>
|
||||||
|
<module>spring-data-mongodb-log4j</module>
|
||||||
<module>spring-data-mongodb-distribution</module>
|
<module>spring-data-mongodb-distribution</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.type>multi</project.type>
|
<project.type>multi</project.type>
|
||||||
<dist.id>spring-data-mongodb</dist.id>
|
<dist.id>spring-data-mongodb</dist.id>
|
||||||
<springdata.commons>2.2.0.M2</springdata.commons>
|
<springdata.commons>1.13.24.BUILD-SNAPSHOT</springdata.commons>
|
||||||
<mongo>3.10.1</mongo>
|
<mongo>2.14.3</mongo>
|
||||||
<mongo.reactivestreams>1.11.0</mongo.reactivestreams>
|
<mongo.osgi>2.13.0</mongo.osgi>
|
||||||
<jmh.version>1.19</jmh.version>
|
<jmh.version>1.19</jmh.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
@@ -39,7 +40,7 @@
|
|||||||
<name>Oliver Gierke</name>
|
<name>Oliver Gierke</name>
|
||||||
<email>ogierke at gopivotal.com</email>
|
<email>ogierke at gopivotal.com</email>
|
||||||
<organization>Pivotal</organization>
|
<organization>Pivotal</organization>
|
||||||
<organizationUrl>http://www.gopivotal.com</organizationUrl>
|
<organizationUrl>https://pivotal.io</organizationUrl>
|
||||||
<roles>
|
<roles>
|
||||||
<role>Project Lead</role>
|
<role>Project Lead</role>
|
||||||
</roles>
|
</roles>
|
||||||
@@ -50,7 +51,7 @@
|
|||||||
<name>Thomas Risberg</name>
|
<name>Thomas Risberg</name>
|
||||||
<email>trisberg at vmware.com</email>
|
<email>trisberg at vmware.com</email>
|
||||||
<organization>Pivotal</organization>
|
<organization>Pivotal</organization>
|
||||||
<organizationUrl>http://www.gopivotal.com</organizationUrl>
|
<organizationUrl>https://pivotal.io</organizationUrl>
|
||||||
<roles>
|
<roles>
|
||||||
<role>Developer</role>
|
<role>Developer</role>
|
||||||
</roles>
|
</roles>
|
||||||
@@ -61,7 +62,7 @@
|
|||||||
<name>Mark Pollack</name>
|
<name>Mark Pollack</name>
|
||||||
<email>mpollack at gopivotal.com</email>
|
<email>mpollack at gopivotal.com</email>
|
||||||
<organization>Pivotal</organization>
|
<organization>Pivotal</organization>
|
||||||
<organizationUrl>http://www.gopivotal.com</organizationUrl>
|
<organizationUrl>https://pivotal.io</organizationUrl>
|
||||||
<roles>
|
<roles>
|
||||||
<role>Developer</role>
|
<role>Developer</role>
|
||||||
</roles>
|
</roles>
|
||||||
@@ -72,7 +73,7 @@
|
|||||||
<name>Jon Brisbin</name>
|
<name>Jon Brisbin</name>
|
||||||
<email>jbrisbin at gopivotal.com</email>
|
<email>jbrisbin at gopivotal.com</email>
|
||||||
<organization>Pivotal</organization>
|
<organization>Pivotal</organization>
|
||||||
<organizationUrl>http://www.gopivotal.com</organizationUrl>
|
<organizationUrl>https://pivotal.io</organizationUrl>
|
||||||
<roles>
|
<roles>
|
||||||
<role>Developer</role>
|
<role>Developer</role>
|
||||||
</roles>
|
</roles>
|
||||||
@@ -83,7 +84,7 @@
|
|||||||
<name>Thomas Darimont</name>
|
<name>Thomas Darimont</name>
|
||||||
<email>tdarimont at gopivotal.com</email>
|
<email>tdarimont at gopivotal.com</email>
|
||||||
<organization>Pivotal</organization>
|
<organization>Pivotal</organization>
|
||||||
<organizationUrl>http://www.gopivotal.com</organizationUrl>
|
<organizationUrl>https://pivotal.io</organizationUrl>
|
||||||
<roles>
|
<roles>
|
||||||
<role>Developer</role>
|
<role>Developer</role>
|
||||||
</roles>
|
</roles>
|
||||||
@@ -94,18 +95,7 @@
|
|||||||
<name>Christoph Strobl</name>
|
<name>Christoph Strobl</name>
|
||||||
<email>cstrobl at gopivotal.com</email>
|
<email>cstrobl at gopivotal.com</email>
|
||||||
<organization>Pivotal</organization>
|
<organization>Pivotal</organization>
|
||||||
<organizationUrl>http://www.gopivotal.com</organizationUrl>
|
<organizationUrl>https://pivotal.io</organizationUrl>
|
||||||
<roles>
|
|
||||||
<role>Developer</role>
|
|
||||||
</roles>
|
|
||||||
<timezone>+1</timezone>
|
|
||||||
</developer>
|
|
||||||
<developer>
|
|
||||||
<id>mpaluch</id>
|
|
||||||
<name>Mark Paluch</name>
|
|
||||||
<email>mpaluch at pivotal.io</email>
|
|
||||||
<organization>Pivotal</organization>
|
|
||||||
<organizationUrl>http://www.pivotal.io</organizationUrl>
|
|
||||||
<roles>
|
<roles>
|
||||||
<role>Developer</role>
|
<role>Developer</role>
|
||||||
</roles>
|
</roles>
|
||||||
@@ -114,18 +104,104 @@
|
|||||||
</developers>
|
</developers>
|
||||||
|
|
||||||
<profiles>
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
|
||||||
|
<id>mongo-next</id>
|
||||||
|
<properties>
|
||||||
|
<mongo>2.15.0-SNAPSHOT</mongo>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>mongo-snapshots</id>
|
||||||
|
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
</profile>
|
||||||
|
|
||||||
<profile>
|
<profile>
|
||||||
<id>release</id>
|
|
||||||
<build>
|
<id>mongo3</id>
|
||||||
<plugins>
|
<properties>
|
||||||
<plugin>
|
<mongo>3.0.4</mongo>
|
||||||
<groupId>org.jfrog.buildinfo</groupId>
|
</properties>
|
||||||
<artifactId>artifactory-maven-plugin</artifactId>
|
|
||||||
<inherited>false</inherited>
|
</profile>
|
||||||
</plugin>
|
|
||||||
</plugins>
|
<profile>
|
||||||
</build>
|
|
||||||
|
<id>mongo3-next</id>
|
||||||
|
<properties>
|
||||||
|
<mongo>3.0.5-SNAPSHOT</mongo>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>mongo-snapshots</id>
|
||||||
|
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
</profile>
|
||||||
|
|
||||||
|
<profile>
|
||||||
|
|
||||||
|
<id>mongo31</id>
|
||||||
|
<properties>
|
||||||
|
<mongo>3.1.1</mongo>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</profile>
|
||||||
|
|
||||||
|
<profile>
|
||||||
|
|
||||||
|
<id>mongo32</id>
|
||||||
|
<properties>
|
||||||
|
<mongo>3.2.2</mongo>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</profile>
|
||||||
|
|
||||||
|
<profile>
|
||||||
|
|
||||||
|
<id>mongo33</id>
|
||||||
|
<properties>
|
||||||
|
<mongo>3.3.0</mongo>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>mongo-snapshots</id>
|
||||||
|
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
</profile>
|
||||||
|
|
||||||
|
<profile>
|
||||||
|
|
||||||
|
<id>mongo34</id>
|
||||||
|
<properties>
|
||||||
|
<mongo>3.4.0</mongo>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</profile>
|
||||||
|
|
||||||
|
<profile>
|
||||||
|
|
||||||
|
<id>mongo34-next</id>
|
||||||
|
<properties>
|
||||||
|
<mongo>3.4.1-SNAPSHOT</mongo>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>mongo-snapshots</id>
|
||||||
|
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
</profile>
|
</profile>
|
||||||
|
|
||||||
<profile>
|
<profile>
|
||||||
@@ -133,10 +209,12 @@
|
|||||||
<modules>
|
<modules>
|
||||||
<module>spring-data-mongodb</module>
|
<module>spring-data-mongodb</module>
|
||||||
<module>spring-data-mongodb-cross-store</module>
|
<module>spring-data-mongodb-cross-store</module>
|
||||||
|
<module>spring-data-mongodb-log4j</module>
|
||||||
<module>spring-data-mongodb-distribution</module>
|
<module>spring-data-mongodb-distribution</module>
|
||||||
<module>spring-data-mongodb-benchmarks</module>
|
<module>spring-data-mongodb-benchmarks</module>
|
||||||
</modules>
|
</modules>
|
||||||
</profile>
|
</profile>
|
||||||
|
|
||||||
</profiles>
|
</profiles>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@@ -150,8 +228,8 @@
|
|||||||
|
|
||||||
<repositories>
|
<repositories>
|
||||||
<repository>
|
<repository>
|
||||||
<id>spring-libs-milestone</id>
|
<id>spring-libs-snapshot</id>
|
||||||
<url>https://repo.spring.io/libs-milestone</url>
|
<url>https://repo.spring.io/libs-snapshot</url>
|
||||||
</repository>
|
</repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
|
|
||||||
@@ -160,11 +238,6 @@
|
|||||||
<id>spring-plugins-release</id>
|
<id>spring-plugins-release</id>
|
||||||
<url>https://repo.spring.io/plugins-release</url>
|
<url>https://repo.spring.io/plugins-release</url>
|
||||||
</pluginRepository>
|
</pluginRepository>
|
||||||
<pluginRepository>
|
|
||||||
<id>spring-libs-milestone</id>
|
|
||||||
<url>https://repo.spring.io/libs-milestone</url>
|
|
||||||
</pluginRepository>
|
|
||||||
|
|
||||||
</pluginRepositories>
|
</pluginRepositories>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?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"
|
<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">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.data</groupId>
|
<groupId>org.springframework.data</groupId>
|
||||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||||
<version>2.2.0.M2</version>
|
<version>1.10.24.BUILD-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
<properties>
|
<properties>
|
||||||
<!-- Skip tests by default; run only if -DskipTests=false is specified or benchmarks profile is activated -->
|
<!-- Skip tests by default; run only if -DskipTests=false is specified or benchmarks profile is activated -->
|
||||||
<skipTests>true</skipTests>
|
<skipTests>true</skipTests>
|
||||||
|
<bundlor.enabled>false</bundlor.enabled>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@@ -87,7 +88,6 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<artifactId>maven-surefire-plugin</artifactId>
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
<configuration>
|
<configuration>
|
||||||
<useSystemClassLoader>false</useSystemClassLoader>
|
|
||||||
<testSourceDirectory>${project.build.sourceDirectory}</testSourceDirectory>
|
<testSourceDirectory>${project.build.sourceDirectory}</testSourceDirectory>
|
||||||
<testClassesDirectory>${project.build.outputDirectory}</testClassesDirectory>
|
<testClassesDirectory>${project.build.outputDirectory}</testClassesDirectory>
|
||||||
<excludes>
|
<excludes>
|
||||||
|
|||||||
@@ -1,180 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* 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.bson.Document;
|
|
||||||
import org.openjdk.jmh.annotations.Benchmark;
|
|
||||||
import org.openjdk.jmh.annotations.Setup;
|
|
||||||
import org.openjdk.jmh.annotations.TearDown;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.data.annotation.Id;
|
|
||||||
import org.springframework.data.mongodb.core.ExecutableFindOperation.FindWithQuery;
|
|
||||||
import org.springframework.data.mongodb.core.ExecutableFindOperation.TerminatingFind;
|
|
||||||
import org.springframework.data.mongodb.core.mapping.Field;
|
|
||||||
import org.springframework.data.mongodb.core.query.BasicQuery;
|
|
||||||
import org.springframework.data.mongodb.microbenchmark.AbstractMicrobenchmark;
|
|
||||||
|
|
||||||
import com.mongodb.MongoClient;
|
|
||||||
import com.mongodb.ServerAddress;
|
|
||||||
import com.mongodb.client.MongoCollection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Christoph Strobl
|
|
||||||
*/
|
|
||||||
public class ProjectionsBenchmark extends AbstractMicrobenchmark {
|
|
||||||
|
|
||||||
private static final String DB_NAME = "projections-benchmark";
|
|
||||||
private static final String COLLECTION_NAME = "projections";
|
|
||||||
|
|
||||||
private MongoTemplate template;
|
|
||||||
private MongoClient client;
|
|
||||||
private MongoCollection<Document> mongoCollection;
|
|
||||||
|
|
||||||
private Person source;
|
|
||||||
|
|
||||||
private FindWithQuery<Person> asPerson;
|
|
||||||
private FindWithQuery<DtoProjection> asDtoProjection;
|
|
||||||
private FindWithQuery<ClosedProjection> asClosedProjection;
|
|
||||||
private FindWithQuery<OpenProjection> asOpenProjection;
|
|
||||||
|
|
||||||
private TerminatingFind<Person> asPersonWithFieldsRestriction;
|
|
||||||
private Document fields = new Document("firstname", 1);
|
|
||||||
|
|
||||||
@Setup
|
|
||||||
public void setUp() {
|
|
||||||
|
|
||||||
client = new MongoClient(new ServerAddress());
|
|
||||||
template = new MongoTemplate(client, DB_NAME);
|
|
||||||
|
|
||||||
source = new Person();
|
|
||||||
source.firstname = "luke";
|
|
||||||
source.lastname = "skywalker";
|
|
||||||
|
|
||||||
source.address = new Address();
|
|
||||||
source.address.street = "melenium falcon 1";
|
|
||||||
source.address.city = "deathstar";
|
|
||||||
|
|
||||||
template.save(source, COLLECTION_NAME);
|
|
||||||
|
|
||||||
asPerson = template.query(Person.class).inCollection(COLLECTION_NAME);
|
|
||||||
asDtoProjection = template.query(Person.class).inCollection(COLLECTION_NAME).as(DtoProjection.class);
|
|
||||||
asClosedProjection = template.query(Person.class).inCollection(COLLECTION_NAME).as(ClosedProjection.class);
|
|
||||||
asOpenProjection = template.query(Person.class).inCollection(COLLECTION_NAME).as(OpenProjection.class);
|
|
||||||
|
|
||||||
asPersonWithFieldsRestriction = template.query(Person.class).inCollection(COLLECTION_NAME)
|
|
||||||
.matching(new BasicQuery(new Document(), fields));
|
|
||||||
|
|
||||||
mongoCollection = client.getDatabase(DB_NAME).getCollection(COLLECTION_NAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
@TearDown
|
|
||||||
public void tearDown() {
|
|
||||||
|
|
||||||
client.dropDatabase(DB_NAME);
|
|
||||||
client.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the baseline for comparison by using the plain MongoDB java driver api without any additional fluff.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Benchmark // DATAMONGO-1733
|
|
||||||
public Object baseline() {
|
|
||||||
return mongoCollection.find().first();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read into the domain type including all fields.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Benchmark // DATAMONGO-1733
|
|
||||||
public Object readIntoDomainType() {
|
|
||||||
return asPerson.all();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read into the domain type but restrict query to only return one field.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Benchmark // DATAMONGO-1733
|
|
||||||
public Object readIntoDomainTypeRestrictingToOneField() {
|
|
||||||
return asPersonWithFieldsRestriction.all();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read into dto projection that only needs to map one field back.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Benchmark // DATAMONGO-1733
|
|
||||||
public Object readIntoDtoProjectionWithOneField() {
|
|
||||||
return asDtoProjection.all();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read into closed interface projection.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Benchmark // DATAMONGO-1733
|
|
||||||
public Object readIntoClosedProjectionWithOneField() {
|
|
||||||
return asClosedProjection.all();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read into an open projection backed by the mapped domain object.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Benchmark // DATAMONGO-1733
|
|
||||||
public Object readIntoOpenProjection() {
|
|
||||||
return asOpenProjection.all();
|
|
||||||
}
|
|
||||||
|
|
||||||
static class Person {
|
|
||||||
|
|
||||||
@Id String id;
|
|
||||||
String firstname;
|
|
||||||
String lastname;
|
|
||||||
Address address;
|
|
||||||
}
|
|
||||||
|
|
||||||
static class Address {
|
|
||||||
|
|
||||||
String city;
|
|
||||||
String street;
|
|
||||||
}
|
|
||||||
|
|
||||||
static class DtoProjection {
|
|
||||||
|
|
||||||
@Field("firstname") String name;
|
|
||||||
}
|
|
||||||
|
|
||||||
static interface ClosedProjection {
|
|
||||||
|
|
||||||
String getFirstname();
|
|
||||||
}
|
|
||||||
|
|
||||||
static interface OpenProjection {
|
|
||||||
|
|
||||||
@Value("#{target.firstname}")
|
|
||||||
String name();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -58,7 +58,7 @@ public class DbRefMappingBenchmark extends AbstractMicrobenchmark {
|
|||||||
client = new MongoClient(new ServerAddress());
|
client = new MongoClient(new ServerAddress());
|
||||||
template = new MongoTemplate(client, DB_NAME);
|
template = new MongoTemplate(client, DB_NAME);
|
||||||
|
|
||||||
List<RefObject> refObjects = new ArrayList<>();
|
List<RefObject> refObjects = new ArrayList<RefObject>();
|
||||||
for (int i = 0; i < 1; i++) {
|
for (int i = 0; i < 1; i++) {
|
||||||
RefObject o = new RefObject();
|
RefObject o = new RefObject();
|
||||||
template.save(o);
|
template.save(o);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -27,7 +27,6 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.bson.Document;
|
|
||||||
import org.bson.types.ObjectId;
|
import org.bson.types.ObjectId;
|
||||||
import org.openjdk.jmh.annotations.Benchmark;
|
import org.openjdk.jmh.annotations.Benchmark;
|
||||||
import org.openjdk.jmh.annotations.Scope;
|
import org.openjdk.jmh.annotations.Scope;
|
||||||
@@ -41,8 +40,10 @@ import org.springframework.data.mongodb.core.mapping.Field;
|
|||||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||||
import org.springframework.data.mongodb.microbenchmark.AbstractMicrobenchmark;
|
import org.springframework.data.mongodb.microbenchmark.AbstractMicrobenchmark;
|
||||||
|
|
||||||
|
import com.mongodb.BasicDBObject;
|
||||||
import com.mongodb.MongoClient;
|
import com.mongodb.MongoClient;
|
||||||
import com.mongodb.ServerAddress;
|
import com.mongodb.ServerAddress;
|
||||||
|
import com.mongodb.util.JSON;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Christoph Strobl
|
* @author Christoph Strobl
|
||||||
@@ -55,10 +56,10 @@ public class MappingMongoConverterBenchmark extends AbstractMicrobenchmark {
|
|||||||
private MongoClient client;
|
private MongoClient client;
|
||||||
private MongoMappingContext mappingContext;
|
private MongoMappingContext mappingContext;
|
||||||
private MappingMongoConverter converter;
|
private MappingMongoConverter converter;
|
||||||
private Document documentWith2Properties, documentWith2PropertiesAnd1Nested;
|
private BasicDBObject documentWith2Properties, documentWith2PropertiesAnd1Nested;
|
||||||
private Customer objectWith2PropertiesAnd1Nested;
|
private Customer objectWith2PropertiesAnd1Nested;
|
||||||
|
|
||||||
private Document documentWithFlatAndComplexPropertiesPlusListAndMap;
|
private BasicDBObject documentWithFlatAndComplexPropertiesPlusListAndMap;
|
||||||
private SlightlyMoreComplexObject objectWithFlatAndComplexPropertiesPlusListAndMap;
|
private SlightlyMoreComplexObject objectWithFlatAndComplexPropertiesPlusListAndMap;
|
||||||
|
|
||||||
@Setup
|
@Setup
|
||||||
@@ -73,15 +74,15 @@ public class MappingMongoConverterBenchmark extends AbstractMicrobenchmark {
|
|||||||
DbRefResolver dbRefResolver = new DefaultDbRefResolver(new SimpleMongoDbFactory(client, DB_NAME));
|
DbRefResolver dbRefResolver = new DefaultDbRefResolver(new SimpleMongoDbFactory(client, DB_NAME));
|
||||||
|
|
||||||
this.converter = new MappingMongoConverter(dbRefResolver, mappingContext);
|
this.converter = new MappingMongoConverter(dbRefResolver, mappingContext);
|
||||||
this.converter.setCustomConversions(new MongoCustomConversions(Collections.emptyList()));
|
this.converter.setCustomConversions(new CustomConversions(Collections.emptyList()));
|
||||||
this.converter.afterPropertiesSet();
|
this.converter.afterPropertiesSet();
|
||||||
|
|
||||||
// just a flat document
|
// just a flat document
|
||||||
this.documentWith2Properties = new Document("firstname", "Dave").append("lastname", "Matthews");
|
this.documentWith2Properties = new BasicDBObject("firstname", "Dave").append("lastname", "Matthews");
|
||||||
|
|
||||||
// document with a nested one
|
// document with a nested one
|
||||||
Document address = new Document("zipCode", "ABCDE").append("city", "Some Place");
|
BasicDBObject address = new BasicDBObject("zipCode", "ABCDE").append("city", "Some Place");
|
||||||
this.documentWith2PropertiesAnd1Nested = new Document("firstname", "Dave").//
|
this.documentWith2PropertiesAnd1Nested = new BasicDBObject("firstname", "Dave").//
|
||||||
append("lastname", "Matthews").//
|
append("lastname", "Matthews").//
|
||||||
append("address", address);
|
append("address", address);
|
||||||
|
|
||||||
@@ -94,7 +95,7 @@ public class MappingMongoConverterBenchmark extends AbstractMicrobenchmark {
|
|||||||
objectWithFlatAndComplexPropertiesPlusListAndMap.addressList = Arrays.asList(new Address("zip-1", "city-1"),
|
objectWithFlatAndComplexPropertiesPlusListAndMap.addressList = Arrays.asList(new Address("zip-1", "city-1"),
|
||||||
new Address("zip-2", "city-2"));
|
new Address("zip-2", "city-2"));
|
||||||
objectWithFlatAndComplexPropertiesPlusListAndMap.customer = objectWith2PropertiesAnd1Nested;
|
objectWithFlatAndComplexPropertiesPlusListAndMap.customer = objectWith2PropertiesAnd1Nested;
|
||||||
objectWithFlatAndComplexPropertiesPlusListAndMap.customerMap = new LinkedHashMap<>();
|
objectWithFlatAndComplexPropertiesPlusListAndMap.customerMap = new LinkedHashMap<String, Customer>();
|
||||||
objectWithFlatAndComplexPropertiesPlusListAndMap.customerMap.put("dave", objectWith2PropertiesAnd1Nested);
|
objectWithFlatAndComplexPropertiesPlusListAndMap.customerMap.put("dave", objectWith2PropertiesAnd1Nested);
|
||||||
objectWithFlatAndComplexPropertiesPlusListAndMap.customerMap.put("deborah",
|
objectWithFlatAndComplexPropertiesPlusListAndMap.customerMap.put("deborah",
|
||||||
new Customer("Deborah Anne", "Dyer", new Address("?", "london")));
|
new Customer("Deborah Anne", "Dyer", new Address("?", "london")));
|
||||||
@@ -108,7 +109,7 @@ public class MappingMongoConverterBenchmark extends AbstractMicrobenchmark {
|
|||||||
objectWithFlatAndComplexPropertiesPlusListAndMap.stringTwo = " (╯°□°)╯︵ ┻━┻";
|
objectWithFlatAndComplexPropertiesPlusListAndMap.stringTwo = " (╯°□°)╯︵ ┻━┻";
|
||||||
|
|
||||||
// JSON equivalent of objectWithFlatAndComplexPropertiesPlusListAndMap
|
// JSON equivalent of objectWithFlatAndComplexPropertiesPlusListAndMap
|
||||||
documentWithFlatAndComplexPropertiesPlusListAndMap = Document.parse(
|
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\" }");
|
"{ \"_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\" }");
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -131,9 +132,9 @@ public class MappingMongoConverterBenchmark extends AbstractMicrobenchmark {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark // DATAMONGO-1720
|
@Benchmark // DATAMONGO-1720
|
||||||
public Document writeObjectWith2PropertiesAnd1NestedObject() {
|
public BasicDBObject writeObjectWith2PropertiesAnd1NestedObject() {
|
||||||
|
|
||||||
Document sink = new Document();
|
BasicDBObject sink = new BasicDBObject();
|
||||||
converter.write(objectWith2PropertiesAnd1Nested, sink);
|
converter.write(objectWith2PropertiesAnd1Nested, sink);
|
||||||
return sink;
|
return sink;
|
||||||
}
|
}
|
||||||
@@ -146,7 +147,7 @@ public class MappingMongoConverterBenchmark extends AbstractMicrobenchmark {
|
|||||||
@Benchmark // DATAMONGO-1720
|
@Benchmark // DATAMONGO-1720
|
||||||
public Object writeObjectWithListAndMapsOfComplexType() {
|
public Object writeObjectWithListAndMapsOfComplexType() {
|
||||||
|
|
||||||
Document sink = new Document();
|
BasicDBObject sink = new BasicDBObject();
|
||||||
converter.write(objectWithFlatAndComplexPropertiesPlusListAndMap, sink);
|
converter.write(objectWithFlatAndComplexPropertiesPlusListAndMap, sink);
|
||||||
return sink;
|
return sink;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -34,6 +34,7 @@ import org.openjdk.jmh.runner.options.ChainedOptionsBuilder;
|
|||||||
import org.openjdk.jmh.runner.options.OptionsBuilder;
|
import org.openjdk.jmh.runner.options.OptionsBuilder;
|
||||||
import org.openjdk.jmh.runner.options.TimeValue;
|
import org.openjdk.jmh.runner.options.TimeValue;
|
||||||
import org.springframework.core.env.StandardEnvironment;
|
import org.springframework.core.env.StandardEnvironment;
|
||||||
|
import org.springframework.data.mongodb.microbenchmark.ResultsWriter.Utils;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.util.ResourceUtils;
|
import org.springframework.util.ResourceUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
@@ -320,7 +321,7 @@ public class AbstractMicrobenchmark {
|
|||||||
|
|
||||||
String uri = environment.getProperty("publishTo");
|
String uri = environment.getProperty("publishTo");
|
||||||
try {
|
try {
|
||||||
ResultsWriter.forUri(uri).write(results);
|
Utils.forUri(uri).write(results);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.err.println(String.format("Cannot save benchmark results to '%s'. Error was %s.", uri, e));
|
System.err.println(String.format("Cannot save benchmark results to '%s'. Error was %s.", uri, e));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -21,8 +21,7 @@ import java.io.OutputStream;
|
|||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLConnection;
|
import java.net.URLConnection;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.Charset;
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import org.openjdk.jmh.results.RunResult;
|
import org.openjdk.jmh.results.RunResult;
|
||||||
@@ -58,8 +57,8 @@ class HttpResultsWriter implements ResultsWriter {
|
|||||||
String gitCommitId = env.getProperty("git.commit.id", "unknown");
|
String gitCommitId = env.getProperty("git.commit.id", "unknown");
|
||||||
|
|
||||||
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
|
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
|
||||||
connection.setConnectTimeout((int) Duration.ofSeconds(1).toMillis());
|
connection.setConnectTimeout(1000);
|
||||||
connection.setReadTimeout((int) Duration.ofSeconds(1).toMillis());
|
connection.setReadTimeout(1000);
|
||||||
connection.setDoOutput(true);
|
connection.setDoOutput(true);
|
||||||
connection.setRequestMethod("POST");
|
connection.setRequestMethod("POST");
|
||||||
|
|
||||||
@@ -69,8 +68,14 @@ class HttpResultsWriter implements ResultsWriter {
|
|||||||
connection.addRequestProperty("X-Git-Dirty", gitDirty);
|
connection.addRequestProperty("X-Git-Dirty", gitDirty);
|
||||||
connection.addRequestProperty("X-Git-Commit-Id", gitCommitId);
|
connection.addRequestProperty("X-Git-Commit-Id", gitCommitId);
|
||||||
|
|
||||||
try (OutputStream output = connection.getOutputStream()) {
|
OutputStream output = null;
|
||||||
output.write(ResultsWriter.jsonifyResults(results).getBytes(StandardCharsets.UTF_8));
|
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) {
|
if (connection.getResponseCode() >= 400) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -15,20 +15,20 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.mongodb.microbenchmark;
|
package org.springframework.data.mongodb.microbenchmark;
|
||||||
|
|
||||||
|
import java.net.UnknownHostException;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.bson.Document;
|
|
||||||
import org.openjdk.jmh.results.RunResult;
|
import org.openjdk.jmh.results.RunResult;
|
||||||
import org.springframework.core.env.StandardEnvironment;
|
import org.springframework.core.env.StandardEnvironment;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
import com.mongodb.BasicDBObject;
|
||||||
|
import com.mongodb.DB;
|
||||||
import com.mongodb.MongoClient;
|
import com.mongodb.MongoClient;
|
||||||
import com.mongodb.MongoClientURI;
|
import com.mongodb.MongoClientURI;
|
||||||
import com.mongodb.client.MongoDatabase;
|
|
||||||
import com.mongodb.util.JSON;
|
import com.mongodb.util.JSON;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -57,16 +57,22 @@ class MongoResultsWriter implements ResultsWriter {
|
|||||||
String gitCommitId = env.getProperty("git.commit.id", "unknown");
|
String gitCommitId = env.getProperty("git.commit.id", "unknown");
|
||||||
|
|
||||||
MongoClientURI uri = new MongoClientURI(this.uri);
|
MongoClientURI uri = new MongoClientURI(this.uri);
|
||||||
MongoClient client = new MongoClient(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";
|
String dbName = StringUtils.hasText(uri.getDatabase()) ? uri.getDatabase() : "spring-data-mongodb-benchmarks";
|
||||||
MongoDatabase db = client.getDatabase(dbName);
|
DB db = client.getDB(dbName);
|
||||||
|
|
||||||
for (BasicDBObject dbo : (List<BasicDBObject>) JSON.parse(ResultsWriter.jsonifyResults(results))) {
|
for (BasicDBObject dbo : (List<BasicDBObject>) JSON.parse(Utils.jsonifyResults(results))) {
|
||||||
|
|
||||||
String collectionName = extractClass(dbo.get("benchmark").toString());
|
String collectionName = extractClass(dbo.get("benchmark").toString());
|
||||||
|
|
||||||
Document sink = new Document();
|
BasicDBObject sink = new BasicDBObject();
|
||||||
sink.append("_version", projectVersion);
|
sink.append("_version", projectVersion);
|
||||||
sink.append("_branch", gitBranch);
|
sink.append("_branch", gitBranch);
|
||||||
sink.append("_commit", gitCommitId);
|
sink.append("_commit", gitCommitId);
|
||||||
@@ -75,9 +81,9 @@ class MongoResultsWriter implements ResultsWriter {
|
|||||||
sink.append("_date", now);
|
sink.append("_date", now);
|
||||||
sink.append("_snapshot", projectVersion.toLowerCase().contains("snapshot"));
|
sink.append("_snapshot", projectVersion.toLowerCase().contains("snapshot"));
|
||||||
|
|
||||||
sink.putAll(dbo);
|
sink.putAll(dbo.toMap());
|
||||||
|
|
||||||
db.getCollection(collectionName).insertOne(fixDocumentKeys(sink));
|
db.getCollection(collectionName).insert(fixDocumentKeys(sink));
|
||||||
}
|
}
|
||||||
|
|
||||||
client.close();
|
client.close();
|
||||||
@@ -89,17 +95,15 @@ class MongoResultsWriter implements ResultsWriter {
|
|||||||
* @param doc
|
* @param doc
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private Document fixDocumentKeys(Document doc) {
|
private BasicDBObject fixDocumentKeys(BasicDBObject doc) {
|
||||||
|
|
||||||
Document sanitized = new Document();
|
BasicDBObject sanitized = new BasicDBObject();
|
||||||
|
|
||||||
for (Object key : doc.keySet()) {
|
for (Object key : doc.keySet()) {
|
||||||
|
|
||||||
Object value = doc.get(key);
|
Object value = doc.get(key);
|
||||||
if (value instanceof Document) {
|
if (value instanceof BasicDBObject) {
|
||||||
value = fixDocumentKeys((Document) value);
|
value = fixDocumentKeys((BasicDBObject) value);
|
||||||
} else if (value instanceof BasicDBObject) {
|
|
||||||
value = fixDocumentKeys(new Document((BasicDBObject) value));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key instanceof String) {
|
if (key instanceof String) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -19,7 +19,7 @@ import lombok.SneakyThrows;
|
|||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.Charset;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import org.openjdk.jmh.results.RunResult;
|
import org.openjdk.jmh.results.RunResult;
|
||||||
@@ -39,29 +39,33 @@ interface ResultsWriter {
|
|||||||
*/
|
*/
|
||||||
void write(Collection<RunResult> results);
|
void write(Collection<RunResult> results);
|
||||||
|
|
||||||
/**
|
/* non Java8 hack */
|
||||||
* Get the uri specific {@link ResultsWriter}.
|
class Utils {
|
||||||
*
|
|
||||||
* @param uri must not be {@literal null}.
|
/**
|
||||||
* @return
|
* Get the uri specific {@link ResultsWriter}.
|
||||||
*/
|
*
|
||||||
static ResultsWriter forUri(String uri) {
|
* @param uri must not be {@literal null}.
|
||||||
return uri.startsWith("mongodb:") ? new MongoResultsWriter(uri) : new HttpResultsWriter(uri);
|
* @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"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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(), StandardCharsets.UTF_8);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?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>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.data</groupId>
|
<groupId>org.springframework.data</groupId>
|
||||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||||
<version>2.2.0.M2</version>
|
<version>1.10.24.BUILD-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
@@ -14,9 +14,8 @@
|
|||||||
<name>Spring Data MongoDB - Cross-Store Support</name>
|
<name>Spring Data MongoDB - Cross-Store Support</name>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<jpa>2.1.1</jpa>
|
<jpa>2.0.0</jpa>
|
||||||
<hibernate>5.2.1.Final</hibernate>
|
<hibernate>3.6.10.Final</hibernate>
|
||||||
<java-module-name>spring.data.mongodb.cross.store</java-module-name>
|
|
||||||
<project.root>${basedir}/..</project.root>
|
<project.root>${basedir}/..</project.root>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
@@ -50,14 +49,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.data</groupId>
|
<groupId>org.springframework.data</groupId>
|
||||||
<artifactId>spring-data-mongodb</artifactId>
|
<artifactId>spring-data-mongodb</artifactId>
|
||||||
<version>2.2.0.M2</version>
|
<version>1.10.24.BUILD-SNAPSHOT</version>
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- reactive -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.projectreactor</groupId>
|
|
||||||
<artifactId>reactor-core</artifactId>
|
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -96,7 +88,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.hibernate</groupId>
|
<groupId>org.hibernate</groupId>
|
||||||
<artifactId>hibernate-validator</artifactId>
|
<artifactId>hibernate-validator</artifactId>
|
||||||
<version>5.2.4.Final</version>
|
<version>4.0.2.GA</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -17,12 +17,6 @@ package org.springframework.data.mongodb.crossstore;
|
|||||||
|
|
||||||
import org.springframework.data.crossstore.ChangeSetBacked;
|
import org.springframework.data.crossstore.ChangeSetBacked;
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Thomas Risberg
|
|
||||||
* @author Oliver Gierke
|
|
||||||
* @deprecated will be removed without replacement.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public interface DocumentBacked extends ChangeSetBacked {
|
public interface DocumentBacked extends ChangeSetBacked {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -17,7 +17,6 @@ package org.springframework.data.mongodb.crossstore;
|
|||||||
|
|
||||||
import javax.persistence.EntityManagerFactory;
|
import javax.persistence.EntityManagerFactory;
|
||||||
|
|
||||||
import org.bson.Document;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.dao.DataAccessException;
|
import org.springframework.dao.DataAccessException;
|
||||||
@@ -30,19 +29,17 @@ import org.springframework.data.mongodb.core.CollectionCallback;
|
|||||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
|
|
||||||
|
import com.mongodb.BasicDBObject;
|
||||||
|
import com.mongodb.DBCollection;
|
||||||
|
import com.mongodb.DBObject;
|
||||||
import com.mongodb.MongoException;
|
import com.mongodb.MongoException;
|
||||||
import com.mongodb.client.MongoCollection;
|
|
||||||
import com.mongodb.client.model.Filters;
|
|
||||||
import com.mongodb.client.result.DeleteResult;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Thomas Risberg
|
* @author Thomas Risberg
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Alex Vengrovsk
|
* @author Alex Vengrovsk
|
||||||
* @author Mark Paluch
|
* @author Mark Paluch
|
||||||
* @deprecated will be removed without replacement.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
||||||
|
|
||||||
private static final String ENTITY_CLASS = "_entity_class";
|
private static final String ENTITY_CLASS = "_entity_class";
|
||||||
@@ -77,15 +74,15 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
|||||||
|
|
||||||
String collName = getCollectionNameForEntity(entityClass);
|
String collName = getCollectionNameForEntity(entityClass);
|
||||||
|
|
||||||
final Document dbk = new Document();
|
final DBObject dbk = new BasicDBObject();
|
||||||
dbk.put(ENTITY_ID, id);
|
dbk.put(ENTITY_ID, id);
|
||||||
dbk.put(ENTITY_CLASS, entityClass.getName());
|
dbk.put(ENTITY_CLASS, entityClass.getName());
|
||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
log.debug("Loading MongoDB data for {}", dbk);
|
log.debug("Loading MongoDB data for {}", dbk);
|
||||||
}
|
}
|
||||||
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
|
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
|
||||||
public Object doInCollection(MongoCollection<Document> collection) throws MongoException, DataAccessException {
|
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||||
for (Document dbo : collection.find(dbk)) {
|
for (DBObject dbo : collection.find(dbk)) {
|
||||||
String key = (String) dbo.get(ENTITY_FIELD_NAME);
|
String key = (String) dbo.get(ENTITY_FIELD_NAME);
|
||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
log.debug("Processing key: {}", key);
|
log.debug("Processing key: {}", key);
|
||||||
@@ -146,31 +143,27 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
|||||||
for (String key : cs.getValues().keySet()) {
|
for (String key : cs.getValues().keySet()) {
|
||||||
if (key != null && !key.startsWith("_") && !key.equals(ChangeSetPersister.ID_KEY)) {
|
if (key != null && !key.startsWith("_") && !key.equals(ChangeSetPersister.ID_KEY)) {
|
||||||
Object value = cs.getValues().get(key);
|
Object value = cs.getValues().get(key);
|
||||||
final Document dbQuery = new Document();
|
final DBObject dbQuery = new BasicDBObject();
|
||||||
dbQuery.put(ENTITY_ID, getPersistentId(entity, cs));
|
dbQuery.put(ENTITY_ID, getPersistentId(entity, cs));
|
||||||
dbQuery.put(ENTITY_CLASS, entity.getClass().getName());
|
dbQuery.put(ENTITY_CLASS, entity.getClass().getName());
|
||||||
dbQuery.put(ENTITY_FIELD_NAME, key);
|
dbQuery.put(ENTITY_FIELD_NAME, key);
|
||||||
final Document dbId = mongoTemplate.execute(collName, new CollectionCallback<Document>() {
|
DBObject dbId = mongoTemplate.execute(collName, new CollectionCallback<DBObject>() {
|
||||||
public Document doInCollection(MongoCollection<Document> collection)
|
public DBObject doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||||
throws MongoException, DataAccessException {
|
return collection.findOne(dbQuery);
|
||||||
Document id = collection.find(dbQuery).first();
|
|
||||||
return id;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
log.debug("Flush: removing: {}", dbQuery);
|
log.debug("Flush: removing: {}", dbQuery);
|
||||||
}
|
}
|
||||||
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
|
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
|
||||||
public Object doInCollection(MongoCollection<Document> collection)
|
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||||
throws MongoException, DataAccessException {
|
collection.remove(dbQuery);
|
||||||
DeleteResult dr = collection.deleteMany(dbQuery);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
final Document dbDoc = new Document();
|
final DBObject dbDoc = new BasicDBObject();
|
||||||
dbDoc.putAll(dbQuery);
|
dbDoc.putAll(dbQuery);
|
||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
log.debug("Flush: saving: {}", dbQuery);
|
log.debug("Flush: saving: {}", dbQuery);
|
||||||
@@ -181,18 +174,8 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
|||||||
dbDoc.put("_id", dbId.get("_id"));
|
dbDoc.put("_id", dbId.get("_id"));
|
||||||
}
|
}
|
||||||
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
|
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
|
||||||
public Object doInCollection(MongoCollection<Document> collection)
|
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||||
throws MongoException, DataAccessException {
|
collection.save(dbDoc);
|
||||||
|
|
||||||
if (dbId != null) {
|
|
||||||
collection.replaceOne(Filters.eq("_id", dbId.get("_id")), dbDoc);
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if (dbDoc.containsKey("_id") && dbDoc.get("_id") == null) {
|
|
||||||
dbDoc.remove("_id");
|
|
||||||
}
|
|
||||||
collection.insertOne(dbDoc);
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -204,7 +187,7 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the collection the given entity type shall be persisted to.
|
* Returns the collection the given entity type shall be persisted to.
|
||||||
*
|
*
|
||||||
* @param entityClass must not be {@literal null}.
|
* @param entityClass must not be {@literal null}.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -40,9 +40,7 @@ import org.springframework.transaction.support.TransactionSynchronizationManager
|
|||||||
* Aspect to turn an object annotated with @Document into a persistent document using Mongo.
|
* Aspect to turn an object annotated with @Document into a persistent document using Mongo.
|
||||||
*
|
*
|
||||||
* @author Thomas Risberg
|
* @author Thomas Risberg
|
||||||
* @deprecated will be removed without replacement.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
public aspect MongoDocumentBacking {
|
public aspect MongoDocumentBacking {
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(MongoDocumentBacking.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(MongoDocumentBacking.class);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -22,9 +22,7 @@ import java.lang.annotation.Target;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Thomas Risberg
|
* @author Thomas Risberg
|
||||||
* @deprecated will be removed without replacement.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target({ ElementType.FIELD })
|
@Target({ ElementType.FIELD })
|
||||||
public @interface RelatedDocument {
|
public @interface RelatedDocument {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -18,7 +18,6 @@ package org.springframework.data.mongodb.crossstore;
|
|||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
import javax.persistence.PersistenceContext;
|
import javax.persistence.PersistenceContext;
|
||||||
|
|
||||||
import org.bson.Document;
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@@ -37,9 +36,11 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
import org.springframework.transaction.support.TransactionCallback;
|
import org.springframework.transaction.support.TransactionCallback;
|
||||||
import org.springframework.transaction.support.TransactionTemplate;
|
import org.springframework.transaction.support.TransactionTemplate;
|
||||||
|
|
||||||
|
import com.mongodb.DBObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Integration tests for MongoDB cross-store persistence (mainly {@link MongoChangeSetPersister}).
|
* Integration tests for MongoDB cross-store persistence (mainly {@link MongoChangeSetPersister}).
|
||||||
*
|
*
|
||||||
* @author Thomas Risberg
|
* @author Thomas Risberg
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
*/
|
*/
|
||||||
@@ -47,11 +48,14 @@ import org.springframework.transaction.support.TransactionTemplate;
|
|||||||
@ContextConfiguration("classpath:/META-INF/spring/applicationContext.xml")
|
@ContextConfiguration("classpath:/META-INF/spring/applicationContext.xml")
|
||||||
public class CrossStoreMongoTests {
|
public class CrossStoreMongoTests {
|
||||||
|
|
||||||
@Autowired MongoTemplate mongoTemplate;
|
@Autowired
|
||||||
|
MongoTemplate mongoTemplate;
|
||||||
|
|
||||||
@PersistenceContext EntityManager entityManager;
|
@PersistenceContext
|
||||||
|
EntityManager entityManager;
|
||||||
|
|
||||||
@Autowired PlatformTransactionManager transactionManager;
|
@Autowired
|
||||||
|
PlatformTransactionManager transactionManager;
|
||||||
TransactionTemplate txTemplate;
|
TransactionTemplate txTemplate;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
@@ -183,7 +187,7 @@ public class CrossStoreMongoTests {
|
|||||||
|
|
||||||
boolean weFound3 = false;
|
boolean weFound3 = false;
|
||||||
|
|
||||||
for (Document dbo : this.mongoTemplate.getCollection(mongoTemplate.getCollectionName(Person.class)).find()) {
|
for (DBObject dbo : this.mongoTemplate.getCollection(mongoTemplate.getCollectionName(Person.class)).find()) {
|
||||||
Assert.assertTrue(!dbo.get("_entity_id").equals(2L));
|
Assert.assertTrue(!dbo.get("_entity_id").equals(2L));
|
||||||
if (dbo.get("_entity_id").equals(3L)) {
|
if (dbo.get("_entity_id").equals(3L)) {
|
||||||
weFound3 = true;
|
weFound3 = true;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
|||||||
@@ -20,13 +20,13 @@
|
|||||||
<mongo:mapping-converter/>
|
<mongo:mapping-converter/>
|
||||||
|
|
||||||
<!-- Mongo config -->
|
<!-- Mongo config -->
|
||||||
<bean id="mongoClient" class="org.springframework.data.mongodb.core.MongoClientFactoryBean">
|
<bean id="mongo" class="org.springframework.data.mongodb.core.MongoFactoryBean">
|
||||||
<property name="host" value="localhost"/>
|
<property name="host" value="localhost"/>
|
||||||
<property name="port" value="27017"/>
|
<property name="port" value="27017"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="mongoDbFactory" class="org.springframework.data.mongodb.core.SimpleMongoDbFactory">
|
<bean id="mongoDbFactory" class="org.springframework.data.mongodb.core.SimpleMongoDbFactory">
|
||||||
<constructor-arg name="mongoClient" ref="mongoClient"/>
|
<constructor-arg name="mongo" ref="mongo"/>
|
||||||
<constructor-arg name="databaseName" value="database"/>
|
<constructor-arg name="databaseName" value="database"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
|||||||
18
spring-data-mongodb-cross-store/template.mf
Normal file
18
spring-data-mongodb-cross-store/template.mf
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
Bundle-SymbolicName: org.springframework.data.mongodb.crossstore
|
||||||
|
Bundle-Name: Spring Data MongoDB Cross Store Support
|
||||||
|
Bundle-Vendor: Pivotal Software, Inc.
|
||||||
|
Bundle-ManifestVersion: 2
|
||||||
|
Import-Package:
|
||||||
|
sun.reflect;version="0";resolution:=optional
|
||||||
|
Export-Template:
|
||||||
|
org.springframework.data.mongodb.crossstore.*;version="${project.version}"
|
||||||
|
Import-Template:
|
||||||
|
com.mongodb.*;version="${mongo.osgi:[=.=.=,+1.0.0)}",
|
||||||
|
javax.persistence.*;version="${jpa:[=.=.=,+1.0.0)}",
|
||||||
|
org.aspectj.*;version="${aspectj:[1.0.0, 2.0.0)}",
|
||||||
|
org.bson.*;version="0",
|
||||||
|
org.slf4j.*;version="${slf4j:[=.=.=,+1.0.0)}",
|
||||||
|
org.springframework.*;version="${spring:[=.=.=.=,+1.0.0)}",
|
||||||
|
org.springframework.data.*;version="${springdata.commons:[=.=.=.=,+1.0.0)}",
|
||||||
|
org.springframework.data.mongodb.*;version="${project.version:[=.=.=.=,+1.0.0)}",
|
||||||
|
org.w3c.dom.*;version="0"
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?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"
|
<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">
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
@@ -14,7 +13,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.data</groupId>
|
<groupId>org.springframework.data</groupId>
|
||||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||||
<version>2.2.0.M2</version>
|
<version>1.10.24.BUILD-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
@@ -29,22 +28,11 @@
|
|||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-assembly-plugin</artifactId>
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
|
||||||
<groupId>org.codehaus.mojo</groupId>
|
|
||||||
<artifactId>wagon-maven-plugin</artifactId>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.asciidoctor</groupId>
|
<groupId>org.asciidoctor</groupId>
|
||||||
<artifactId>asciidoctor-maven-plugin</artifactId>
|
<artifactId>asciidoctor-maven-plugin</artifactId>
|
||||||
<configuration>
|
|
||||||
<attributes>
|
|
||||||
<mongo-reactivestreams>${mongo.reactivestreams}</mongo-reactivestreams>
|
|
||||||
<reactor>${reactor}</reactor>
|
|
||||||
</attributes>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
|
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
52
spring-data-mongodb-log4j/README.md
Normal file
52
spring-data-mongodb-log4j/README.md
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
# MongoDB Log4J Appender
|
||||||
|
|
||||||
|
This module sets up a Log4J appender that puts logging events in MongoDB. It is fully configurable
|
||||||
|
and connects directly to the MongoDB server using the driver. It has no dependency on any Spring package.
|
||||||
|
|
||||||
|
To use it, configure a host, port, (optionally) applicationId, and database property in your Log4J configuration:
|
||||||
|
|
||||||
|
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 = %c
|
||||||
|
log4j.appender.stdout.applicationId = my.application
|
||||||
|
log4j.appender.stdout.warnOrHigherWriteConcern = FSYNC_SAFE
|
||||||
|
|
||||||
|
It will even support properties in your MDC (so long as they're Strings or support .toString()).
|
||||||
|
|
||||||
|
The collection name is configurable as well. If you don't specify anything, it will use the Category name.
|
||||||
|
If you want to specify a collection name, you can give it a Log4J pattern layout format string which will have
|
||||||
|
the following additional MDC variables in the context when the collection name is rendered:
|
||||||
|
|
||||||
|
"year" = Calendar.YEAR
|
||||||
|
"month" = Calendar.MONTH + 1
|
||||||
|
"day" = Calendar.DAY_OF_MONTH
|
||||||
|
"hour" = Calendar.HOUR_OF_DAY
|
||||||
|
"applicationId" = configured applicationId
|
||||||
|
|
||||||
|
An example log entry might look like:
|
||||||
|
|
||||||
|
{
|
||||||
|
"_id" : ObjectId("4d89341a8ef397e06940d5cd"),
|
||||||
|
"applicationId" : "my.application",
|
||||||
|
"name" : "org.springframework.data.mongodb.log4j.MongoLog4jAppenderIntegrationTests",
|
||||||
|
"level" : "DEBUG",
|
||||||
|
"timestamp" : ISODate("2011-03-23T16:53:46.778Z"),
|
||||||
|
"properties" : {
|
||||||
|
"property" : "one"
|
||||||
|
},
|
||||||
|
"message" : "DEBUG message"
|
||||||
|
}
|
||||||
|
|
||||||
|
To set WriteConcern levels for WARN or higher messages, set warnOrHigherWriteConcern to one of the following:
|
||||||
|
|
||||||
|
* FSYNC_SAFE
|
||||||
|
* NONE
|
||||||
|
* NORMAL
|
||||||
|
* REPLICAS_SAFE
|
||||||
|
* SAFE
|
||||||
|
|
||||||
|
[http://api.mongodb.org/java/2.5-pre-/com/mongodb/WriteConcern.html#field_detail](http://api.mongodb.org/java/2.5-pre-/com/mongodb/WriteConcern.html#field_detail)
|
||||||
31
spring-data-mongodb-log4j/pom.xml
Normal file
31
spring-data-mongodb-log4j/pom.xml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?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-log4j</artifactId>
|
||||||
|
<name>Spring Data MongoDB - Log4J Appender</name>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<log4j>1.2.16</log4j>
|
||||||
|
<project.root>${basedir}/..</project.root>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<!-- Logging -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>log4j</groupId>
|
||||||
|
<artifactId>log4j</artifactId>
|
||||||
|
<version>${log4j}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,298 @@
|
|||||||
|
/*
|
||||||
|
* 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.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;
|
||||||
|
import org.apache.log4j.Level;
|
||||||
|
import org.apache.log4j.MDC;
|
||||||
|
import org.apache.log4j.PatternLayout;
|
||||||
|
import org.apache.log4j.spi.LoggingEvent;
|
||||||
|
|
||||||
|
import com.mongodb.BasicDBList;
|
||||||
|
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
|
||||||
|
* @author Christoph Strobl
|
||||||
|
* @author Ricardo Espirito Santo
|
||||||
|
*/
|
||||||
|
public class MongoLog4jAppender extends AppenderSkeleton {
|
||||||
|
|
||||||
|
public static final String LEVEL = "level";
|
||||||
|
public static final String NAME = "name";
|
||||||
|
public static final String APP_ID = "applicationId";
|
||||||
|
public static final String TIMESTAMP = "timestamp";
|
||||||
|
public static final String PROPERTIES = "properties";
|
||||||
|
public static final String TRACEBACK = "traceback";
|
||||||
|
public static final String MESSAGE = "message";
|
||||||
|
public static final String YEAR = "year";
|
||||||
|
public static final String MONTH = "month";
|
||||||
|
public static final String DAY = "day";
|
||||||
|
public static final String HOUR = "hour";
|
||||||
|
|
||||||
|
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);
|
||||||
|
protected String applicationId = System.getProperty("APPLICATION_ID", null);
|
||||||
|
protected WriteConcern warnOrHigherWriteConcern = WriteConcern.ACKNOWLEDGED;
|
||||||
|
protected WriteConcern infoOrLowerWriteConcern = WriteConcern.UNACKNOWLEDGED;
|
||||||
|
protected Mongo mongo;
|
||||||
|
protected DB db;
|
||||||
|
|
||||||
|
public MongoLog4jAppender() {}
|
||||||
|
|
||||||
|
public MongoLog4jAppender(boolean isActive) {
|
||||||
|
super(isActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHost() {
|
||||||
|
return host;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHost(String host) {
|
||||||
|
this.host = host;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPort() {
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPort(int port) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDatabase(String database) {
|
||||||
|
this.database = database;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCollectionPattern() {
|
||||||
|
return collectionPattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCollectionPattern(String collectionPattern) {
|
||||||
|
this.collectionPattern = collectionPattern;
|
||||||
|
this.collectionLayout = new PatternLayout(collectionPattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getApplicationId() {
|
||||||
|
return applicationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setApplicationId(String applicationId) {
|
||||||
|
this.applicationId = applicationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getWarnOrHigherWriteConcern() {
|
||||||
|
return warnOrHigherWriteConcern.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWarnOrHigherWriteConcern(String wc) {
|
||||||
|
this.warnOrHigherWriteConcern = WriteConcern.valueOf(wc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInfoOrLowerWriteConcern() {
|
||||||
|
return infoOrLowerWriteConcern.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInfoOrLowerWriteConcern(String wc) {
|
||||||
|
this.infoOrLowerWriteConcern = WriteConcern.valueOf(wc);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void connectToMongo() throws UnknownHostException {
|
||||||
|
|
||||||
|
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)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings({ "unchecked" })
|
||||||
|
protected void append(final LoggingEvent event) {
|
||||||
|
if (null == db) {
|
||||||
|
try {
|
||||||
|
connectToMongo();
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
throw new RuntimeException(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicDBObject dbo = new BasicDBObject();
|
||||||
|
if (null != applicationId) {
|
||||||
|
dbo.put(APP_ID, applicationId);
|
||||||
|
MDC.put(APP_ID, applicationId);
|
||||||
|
}
|
||||||
|
dbo.put(NAME, event.getLogger().getName());
|
||||||
|
dbo.put(LEVEL, event.getLevel().toString());
|
||||||
|
Calendar tstamp = Calendar.getInstance();
|
||||||
|
tstamp.setTimeInMillis(event.getTimeStamp());
|
||||||
|
dbo.put(TIMESTAMP, tstamp.getTime());
|
||||||
|
|
||||||
|
// Copy properties into document
|
||||||
|
Map<Object, Object> props = event.getProperties();
|
||||||
|
if (null != props && !props.isEmpty()) {
|
||||||
|
BasicDBObject propsDbo = new BasicDBObject();
|
||||||
|
for (Map.Entry<Object, Object> entry : props.entrySet()) {
|
||||||
|
propsDbo.put(entry.getKey().toString(), entry.getValue().toString());
|
||||||
|
}
|
||||||
|
dbo.put(PROPERTIES, propsDbo);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy traceback info (if there is any) into the document
|
||||||
|
String[] traceback = event.getThrowableStrRep();
|
||||||
|
if (null != traceback && traceback.length > 0) {
|
||||||
|
BasicDBList tbDbo = new BasicDBList();
|
||||||
|
tbDbo.addAll(Arrays.asList(traceback));
|
||||||
|
dbo.put(TRACEBACK, tbDbo);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put the rendered message into the document
|
||||||
|
dbo.put(MESSAGE, event.getRenderedMessage());
|
||||||
|
|
||||||
|
// Insert the document
|
||||||
|
Calendar now = Calendar.getInstance();
|
||||||
|
MDC.put(YEAR, now.get(Calendar.YEAR));
|
||||||
|
MDC.put(MONTH, String.format("%1$02d", now.get(Calendar.MONTH) + 1));
|
||||||
|
MDC.put(DAY, String.format("%1$02d", now.get(Calendar.DAY_OF_MONTH)));
|
||||||
|
MDC.put(HOUR, String.format("%1$02d", now.get(Calendar.HOUR_OF_DAY)));
|
||||||
|
|
||||||
|
String coll = collectionLayout.format(event);
|
||||||
|
|
||||||
|
MDC.remove(YEAR);
|
||||||
|
MDC.remove(MONTH);
|
||||||
|
MDC.remove(DAY);
|
||||||
|
MDC.remove(HOUR);
|
||||||
|
if (null != applicationId) {
|
||||||
|
MDC.remove(APP_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteConcern wc;
|
||||||
|
if (event.getLevel().isGreaterOrEqual(Level.WARN)) {
|
||||||
|
wc = warnOrHigherWriteConcern;
|
||||||
|
} else {
|
||||||
|
wc = infoOrLowerWriteConcern;
|
||||||
|
}
|
||||||
|
db.getCollection(coll).insert(dbo, wc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.apache.log4j.AppenderSkeleton#close()
|
||||||
|
*/
|
||||||
|
public void close() {
|
||||||
|
|
||||||
|
if (mongo != null) {
|
||||||
|
mongo.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.apache.log4j.AppenderSkeleton#requiresLayout()
|
||||||
|
*/
|
||||||
|
public boolean requiresLayout() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
/**
|
||||||
|
* Infrastructure for to use MongoDB as a logging sink.
|
||||||
|
*/
|
||||||
|
package org.springframework.data.mongodb.log4j;
|
||||||
|
|
||||||
@@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* 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.log4j;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
|
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;
|
||||||
|
|
||||||
|
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 {
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
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
|
||||||
|
public void tearDown() {
|
||||||
|
db.getCollection(collection).remove(new BasicDBObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
@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");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2017-2019 the original author or authors.
|
* Copyright 2013-2019 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -13,15 +13,19 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.springframework.data.mongodb.repository;
|
package org.springframework.data.mongodb.log4j;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.junit.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Unit tests for {@link MongoLog4jAppender}.
|
||||||
|
*
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
*/
|
*/
|
||||||
public interface PersonExcerpt {
|
public class MongoLog4jAppenderUnitTests {
|
||||||
|
|
||||||
@Value("#{target.firstname + ' ' + target.lastname}")
|
@Test // DATAMONGO-641
|
||||||
String getFullName();
|
public void closesWithoutMongoInstancePresent() {
|
||||||
|
new MongoLog4jAppender().close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
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.collectionPattern = %X{year}%X{month}
|
||||||
|
log4j.appender.mongo.applicationId = my.application
|
||||||
|
log4j.appender.mongo.warnOrHigherWriteConcern = FSYNC_SAFE
|
||||||
|
|
||||||
|
log4j.category.org.springframework.data.mongodb=DEBUG
|
||||||
9
spring-data-mongodb-log4j/template.mf
Normal file
9
spring-data-mongodb-log4j/template.mf
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
Bundle-SymbolicName: org.springframework.data.mongodb.log4j
|
||||||
|
Bundle-Name: Spring Data Mongo DB Log4J Appender
|
||||||
|
Bundle-Vendor: Pivotal Software, Inc.
|
||||||
|
Bundle-ManifestVersion: 2
|
||||||
|
Import-Package:
|
||||||
|
sun.reflect;version="0";resolution:=optional
|
||||||
|
Import-Template:
|
||||||
|
com.mongodb.*;version="${mongo.osgi:[=.=.=,+1.0.0)}",
|
||||||
|
org.apache.log4j.*;version="${log4j:[=.=.=,+1.0.0)}"
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?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>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
@@ -11,16 +11,14 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.data</groupId>
|
<groupId>org.springframework.data</groupId>
|
||||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||||
<version>2.2.0.M2</version>
|
<version>1.10.24.BUILD-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<objenesis>1.3</objenesis>
|
<objenesis>1.3</objenesis>
|
||||||
<equalsverifier>1.7.8</equalsverifier>
|
<equalsverifier>1.5</equalsverifier>
|
||||||
<java-module-name>spring.data.mongodb</java-module-name>
|
|
||||||
<project.root>${basedir}/..</project.root>
|
<project.root>${basedir}/..</project.root>
|
||||||
<multithreadedtc>1.01</multithreadedtc>
|
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@@ -81,80 +79,7 @@
|
|||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- reactive -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.mongodb</groupId>
|
|
||||||
<artifactId>mongodb-driver-reactivestreams</artifactId>
|
|
||||||
<version>${mongo.reactivestreams}</version>
|
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.mongodb</groupId>
|
|
||||||
<artifactId>mongodb-driver-async</artifactId>
|
|
||||||
<version>${mongo}</version>
|
|
||||||
<optional>true</optional>
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.mongodb</groupId>
|
|
||||||
<artifactId>mongodb-driver-core</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.mongodb</groupId>
|
|
||||||
<artifactId>bson</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.projectreactor</groupId>
|
|
||||||
<artifactId>reactor-core</artifactId>
|
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.projectreactor</groupId>
|
|
||||||
<artifactId>reactor-test</artifactId>
|
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.reactivex</groupId>
|
|
||||||
<artifactId>rxjava</artifactId>
|
|
||||||
<version>${rxjava}</version>
|
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.reactivex</groupId>
|
|
||||||
<artifactId>rxjava-reactive-streams</artifactId>
|
|
||||||
<version>${rxjava-reactive-streams}</version>
|
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.reactivex.rxjava2</groupId>
|
|
||||||
<artifactId>rxjava</artifactId>
|
|
||||||
<version>${rxjava2}</version>
|
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- CDI -->
|
<!-- CDI -->
|
||||||
<!-- Dependency order required to build against CDI 1.0 and test with CDI 2.0 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.geronimo.specs</groupId>
|
|
||||||
<artifactId>geronimo-jcdi_2.0_spec</artifactId>
|
|
||||||
<version>1.0.1</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>javax.interceptor</groupId>
|
|
||||||
<artifactId>javax.interceptor-api</artifactId>
|
|
||||||
<version>1.2.1</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.enterprise</groupId>
|
<groupId>javax.enterprise</groupId>
|
||||||
<artifactId>cdi-api</artifactId>
|
<artifactId>cdi-api</artifactId>
|
||||||
@@ -164,19 +89,26 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.annotation</groupId>
|
<groupId>javax.el</groupId>
|
||||||
<artifactId>javax.annotation-api</artifactId>
|
<artifactId>el-api</artifactId>
|
||||||
<version>${javax-annotation-api}</version>
|
<version>${cdi}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.openwebbeans</groupId>
|
<groupId>org.apache.openwebbeans.test</groupId>
|
||||||
<artifactId>openwebbeans-se</artifactId>
|
<artifactId>cditest-owb</artifactId>
|
||||||
<version>${webbeans}</version>
|
<version>${webbeans}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.servlet</groupId>
|
||||||
|
<artifactId>servlet-api</artifactId>
|
||||||
|
<version>2.5</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- JSR 303 Validation -->
|
<!-- JSR 303 Validation -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.validation</groupId>
|
<groupId>javax.validation</groupId>
|
||||||
@@ -195,7 +127,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.hibernate</groupId>
|
<groupId>org.hibernate</groupId>
|
||||||
<artifactId>hibernate-validator</artifactId>
|
<artifactId>hibernate-validator</artifactId>
|
||||||
<version>5.2.4.Final</version>
|
<version>4.2.0.Final</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
@@ -239,65 +171,9 @@
|
|||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>de.schauderhaft.degraph</groupId>
|
|
||||||
<artifactId>degraph-check</artifactId>
|
|
||||||
<version>0.1.4</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>edu.umd.cs.mtc</groupId>
|
|
||||||
<artifactId>multithreadedtc</artifactId>
|
|
||||||
<version>${multithreadedtc}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>javax.transaction</groupId>
|
|
||||||
<artifactId>jta</artifactId>
|
|
||||||
<version>1.1</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- Kotlin extension -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jetbrains.kotlin</groupId>
|
|
||||||
<artifactId>kotlin-stdlib</artifactId>
|
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jetbrains.kotlin</groupId>
|
|
||||||
<artifactId>kotlin-reflect</artifactId>
|
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jetbrains.kotlinx</groupId>
|
|
||||||
<artifactId>kotlinx-coroutines-core</artifactId>
|
|
||||||
<version>${kotlin-coroutines}</version>
|
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jetbrains.kotlinx</groupId>
|
|
||||||
<artifactId>kotlinx-coroutines-reactor</artifactId>
|
|
||||||
<version>${kotlin-coroutines}</version>
|
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.mockk</groupId>
|
|
||||||
<artifactId>mockk</artifactId>
|
|
||||||
<version>${mockk}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
||||||
<plugins>
|
<plugins>
|
||||||
|
|
||||||
<plugin>
|
<plugin>
|
||||||
@@ -328,19 +204,17 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-surefire-plugin</artifactId>
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>2.12</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<useSystemClassLoader>false</useSystemClassLoader>
|
|
||||||
<useFile>false</useFile>
|
<useFile>false</useFile>
|
||||||
<includes>
|
<includes>
|
||||||
<include>**/*Tests.java</include>
|
<include>**/*Tests.java</include>
|
||||||
</includes>
|
</includes>
|
||||||
<excludes>
|
<excludes>
|
||||||
<exclude>**/PerformanceTests.java</exclude>
|
<exclude>**/PerformanceTests.java</exclude>
|
||||||
<exclude>**/ReactivePerformanceTests.java</exclude>
|
|
||||||
</excludes>
|
</excludes>
|
||||||
<systemPropertyVariables>
|
<systemPropertyVariables>
|
||||||
<java.util.logging.config.file>src/test/resources/logging.properties</java.util.logging.config.file>
|
<java.util.logging.config.file>src/test/resources/logging.properties</java.util.logging.config.file>
|
||||||
<reactor.trace.cancel>true</reactor.trace.cancel>
|
|
||||||
</systemPropertyVariables>
|
</systemPropertyVariables>
|
||||||
<properties>
|
<properties>
|
||||||
<property>
|
<property>
|
||||||
@@ -350,8 +224,6 @@
|
|||||||
</properties>
|
</properties>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
</plugins>
|
</plugins>
|
||||||
|
|
||||||
</build>
|
</build>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -25,7 +25,7 @@ import com.mongodb.BulkWriteResult;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Is thrown when errors occur during bulk operations.
|
* Is thrown when errors occur during bulk operations.
|
||||||
*
|
*
|
||||||
* @author Tobias Trelle
|
* @author Tobias Trelle
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @since 1.9
|
* @since 1.9
|
||||||
@@ -39,7 +39,7 @@ public class BulkOperationException extends DataAccessException {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link BulkOperationException} with the given message and source {@link BulkWriteException}.
|
* Creates a new {@link BulkOperationException} with the given message and source {@link BulkWriteException}.
|
||||||
*
|
*
|
||||||
* @param message must not be {@literal null}.
|
* @param message must not be {@literal null}.
|
||||||
* @param source must not be {@literal null}.
|
* @param source must not be {@literal null}.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -17,18 +17,16 @@ package org.springframework.data.mongodb;
|
|||||||
|
|
||||||
import org.springframework.dao.DataAccessResourceFailureException;
|
import org.springframework.dao.DataAccessResourceFailureException;
|
||||||
import org.springframework.data.authentication.UserCredentials;
|
import org.springframework.data.authentication.UserCredentials;
|
||||||
import org.springframework.lang.Nullable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exception being thrown in case we cannot connect to a MongoDB instance.
|
* Exception being thrown in case we cannot connect to a MongoDB instance.
|
||||||
*
|
*
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Mark Paluch
|
|
||||||
*/
|
*/
|
||||||
public class CannotGetMongoDbConnectionException extends DataAccessResourceFailureException {
|
public class CannotGetMongoDbConnectionException extends DataAccessResourceFailureException {
|
||||||
|
|
||||||
private final UserCredentials credentials;
|
private final UserCredentials credentials;
|
||||||
private final @Nullable String database;
|
private final String database;
|
||||||
|
|
||||||
private static final long serialVersionUID = 1172099106475265589L;
|
private static final long serialVersionUID = 1172099106475265589L;
|
||||||
|
|
||||||
@@ -42,7 +40,7 @@ public class CannotGetMongoDbConnectionException extends DataAccessResourceFailu
|
|||||||
this(msg, null, UserCredentials.NO_CREDENTIALS);
|
this(msg, null, UserCredentials.NO_CREDENTIALS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CannotGetMongoDbConnectionException(String msg, @Nullable String database, UserCredentials credentials) {
|
public CannotGetMongoDbConnectionException(String msg, String database, UserCredentials credentials) {
|
||||||
super(msg);
|
super(msg);
|
||||||
this.database = database;
|
this.database = database;
|
||||||
this.credentials = credentials;
|
this.credentials = credentials;
|
||||||
@@ -50,7 +48,7 @@ public class CannotGetMongoDbConnectionException extends DataAccessResourceFailu
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link UserCredentials} that were used when trying to connect to the MongoDB instance.
|
* Returns the {@link UserCredentials} that were used when trying to connect to the MongoDB instance.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public UserCredentials getCredentials() {
|
public UserCredentials getCredentials() {
|
||||||
@@ -59,10 +57,9 @@ public class CannotGetMongoDbConnectionException extends DataAccessResourceFailu
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the name of the database trying to be accessed.
|
* Returns the name of the database trying to be accessed.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@Nullable
|
|
||||||
public String getDatabase() {
|
public String getDatabase() {
|
||||||
return database;
|
return database;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
import org.springframework.dao.NonTransientDataAccessException;
|
|
||||||
import org.springframework.lang.Nullable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link NonTransientDataAccessException} specific to MongoDB {@link com.mongodb.session.ClientSession} related data
|
|
||||||
* access failures such as reading data using an already closed session.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 2.1
|
|
||||||
*/
|
|
||||||
public class ClientSessionException extends NonTransientDataAccessException {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for {@link ClientSessionException}.
|
|
||||||
*
|
|
||||||
* @param msg the detail message. Must not be {@literal null}.
|
|
||||||
*/
|
|
||||||
public ClientSessionException(String msg) {
|
|
||||||
super(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for {@link ClientSessionException}.
|
|
||||||
*
|
|
||||||
* @param msg the detail message. Can be {@literal null}.
|
|
||||||
* @param cause the root cause. Can be {@literal null}.
|
|
||||||
*/
|
|
||||||
public ClientSessionException(@Nullable String msg, @Nullable Throwable cause) {
|
|
||||||
super(msg, cause);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import org.bson.codecs.Codec;
|
|
||||||
import org.bson.codecs.configuration.CodecConfigurationException;
|
|
||||||
import org.bson.codecs.configuration.CodecRegistry;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provider interface to obtain {@link CodecRegistry} from the underlying MongoDB Java driver.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @author Mark Paluch
|
|
||||||
* @since 2.1
|
|
||||||
*/
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface CodecRegistryProvider {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the underlying {@link CodecRegistry} used by the MongoDB Java driver.
|
|
||||||
*
|
|
||||||
* @return never {@literal null}.
|
|
||||||
* @throws IllegalStateException if {@link CodecRegistry} cannot be obtained.
|
|
||||||
*/
|
|
||||||
CodecRegistry getCodecRegistry();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if a {@link Codec} is registered for a given type.
|
|
||||||
*
|
|
||||||
* @param type must not be {@literal null}.
|
|
||||||
* @return true if {@link #getCodecRegistry()} holds a {@link Codec} for given type.
|
|
||||||
* @throws IllegalStateException if {@link CodecRegistry} cannot be obtained.
|
|
||||||
*/
|
|
||||||
default boolean hasCodecFor(Class<?> type) {
|
|
||||||
return getCodecFor(type).isPresent();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the {@link Codec} registered for the given {@literal type} or an {@link Optional#empty() empty Optional}
|
|
||||||
* instead.
|
|
||||||
*
|
|
||||||
* @param type must not be {@literal null}.
|
|
||||||
* @param <T>
|
|
||||||
* @return never {@literal null}.
|
|
||||||
* @throws IllegalArgumentException if {@literal type} is {@literal null}.
|
|
||||||
*/
|
|
||||||
default <T> Optional<Codec<T>> getCodecFor(Class<T> type) {
|
|
||||||
|
|
||||||
Assert.notNull(type, "Type must not be null!");
|
|
||||||
|
|
||||||
try {
|
|
||||||
return Optional.of(getCodecRegistry().get(type));
|
|
||||||
} catch (CodecConfigurationException e) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -23,7 +23,7 @@ import org.springframework.util.StringUtils;
|
|||||||
* <p/>
|
* <p/>
|
||||||
* <p/>
|
* <p/>
|
||||||
* Mainly intended for internal use within the framework.
|
* Mainly intended for internal use within the framework.
|
||||||
*
|
*
|
||||||
* @author Thomas Risberg
|
* @author Thomas Risberg
|
||||||
* @since 1.0
|
* @since 1.0
|
||||||
*/
|
*/
|
||||||
@@ -38,7 +38,7 @@ public abstract class MongoCollectionUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtains the collection name to use for the provided class
|
* Obtains the collection name to use for the provided class
|
||||||
*
|
*
|
||||||
* @param entityClass The class to determine the preferred collection name for
|
* @param entityClass The class to determine the preferred collection name for
|
||||||
* @return The preferred collection name
|
* @return The preferred collection name
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,240 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
import org.springframework.lang.Nullable;
|
|
||||||
import org.springframework.transaction.support.ResourceHolderSynchronization;
|
|
||||||
import org.springframework.transaction.support.TransactionSynchronization;
|
|
||||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import com.mongodb.ClientSessionOptions;
|
|
||||||
import com.mongodb.client.ClientSession;
|
|
||||||
import com.mongodb.client.MongoDatabase;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper class for managing a {@link MongoDatabase} instances via {@link MongoDbFactory}. Used for obtaining
|
|
||||||
* {@link ClientSession session bound} resources, such as {@link MongoDatabase} and
|
|
||||||
* {@link com.mongodb.client.MongoCollection} suitable for transactional usage.
|
|
||||||
* <p />
|
|
||||||
* <strong>Note:</strong> Intended for internal usage only.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @author Mark Paluch
|
|
||||||
* @currentRead Shadow's Edge - Brent Weeks
|
|
||||||
* @since 2.1
|
|
||||||
*/
|
|
||||||
public class MongoDatabaseUtils {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain the default {@link MongoDatabase database} form the given {@link MongoDbFactory factory} using
|
|
||||||
* {@link SessionSynchronization#ON_ACTUAL_TRANSACTION native session synchronization}.
|
|
||||||
* <p />
|
|
||||||
* Registers a {@link MongoSessionSynchronization MongoDB specific transaction synchronization} within the current
|
|
||||||
* {@link Thread} if {@link TransactionSynchronizationManager#isSynchronizationActive() synchronization is active}.
|
|
||||||
*
|
|
||||||
* @param factory the {@link MongoDbFactory} to get the {@link MongoDatabase} from.
|
|
||||||
* @return the {@link MongoDatabase} that is potentially associated with a transactional {@link ClientSession}.
|
|
||||||
*/
|
|
||||||
public static MongoDatabase getDatabase(MongoDbFactory factory) {
|
|
||||||
return doGetMongoDatabase(null, factory, SessionSynchronization.ON_ACTUAL_TRANSACTION);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain the default {@link MongoDatabase database} form the given {@link MongoDbFactory factory}.
|
|
||||||
* <p />
|
|
||||||
* Registers a {@link MongoSessionSynchronization MongoDB specific transaction synchronization} within the current
|
|
||||||
* {@link Thread} if {@link TransactionSynchronizationManager#isSynchronizationActive() synchronization is active}.
|
|
||||||
*
|
|
||||||
* @param factory the {@link MongoDbFactory} to get the {@link MongoDatabase} from.
|
|
||||||
* @param sessionSynchronization the synchronization to use. Must not be {@literal null}.
|
|
||||||
* @return the {@link MongoDatabase} that is potentially associated with a transactional {@link ClientSession}.
|
|
||||||
*/
|
|
||||||
public static MongoDatabase getDatabase(MongoDbFactory factory, SessionSynchronization sessionSynchronization) {
|
|
||||||
return doGetMongoDatabase(null, factory, sessionSynchronization);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain the {@link MongoDatabase database} with given name form the given {@link MongoDbFactory factory} using
|
|
||||||
* {@link SessionSynchronization#ON_ACTUAL_TRANSACTION native session synchronization}.
|
|
||||||
* <p />
|
|
||||||
* Registers a {@link MongoSessionSynchronization MongoDB specific transaction synchronization} within the current
|
|
||||||
* {@link Thread} if {@link TransactionSynchronizationManager#isSynchronizationActive() synchronization is active}.
|
|
||||||
*
|
|
||||||
* @param dbName the name of the {@link MongoDatabase} to get.
|
|
||||||
* @param factory the {@link MongoDbFactory} to get the {@link MongoDatabase} from.
|
|
||||||
* @return the {@link MongoDatabase} that is potentially associated with a transactional {@link ClientSession}.
|
|
||||||
*/
|
|
||||||
public static MongoDatabase getDatabase(String dbName, MongoDbFactory factory) {
|
|
||||||
return doGetMongoDatabase(dbName, factory, SessionSynchronization.ON_ACTUAL_TRANSACTION);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain the {@link MongoDatabase database} with given name form the given {@link MongoDbFactory factory}.
|
|
||||||
* <p />
|
|
||||||
* Registers a {@link MongoSessionSynchronization MongoDB specific transaction synchronization} within the current
|
|
||||||
* {@link Thread} if {@link TransactionSynchronizationManager#isSynchronizationActive() synchronization is active}.
|
|
||||||
*
|
|
||||||
* @param dbName the name of the {@link MongoDatabase} to get.
|
|
||||||
* @param factory the {@link MongoDbFactory} to get the {@link MongoDatabase} from.
|
|
||||||
* @param sessionSynchronization the synchronization to use. Must not be {@literal null}.
|
|
||||||
* @return the {@link MongoDatabase} that is potentially associated with a transactional {@link ClientSession}.
|
|
||||||
*/
|
|
||||||
public static MongoDatabase getDatabase(String dbName, MongoDbFactory factory,
|
|
||||||
SessionSynchronization sessionSynchronization) {
|
|
||||||
return doGetMongoDatabase(dbName, factory, sessionSynchronization);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static MongoDatabase doGetMongoDatabase(@Nullable String dbName, MongoDbFactory factory,
|
|
||||||
SessionSynchronization sessionSynchronization) {
|
|
||||||
|
|
||||||
Assert.notNull(factory, "Factory must not be null!");
|
|
||||||
|
|
||||||
if (!TransactionSynchronizationManager.isSynchronizationActive()) {
|
|
||||||
return StringUtils.hasText(dbName) ? factory.getDb(dbName) : factory.getDb();
|
|
||||||
}
|
|
||||||
|
|
||||||
ClientSession session = doGetSession(factory, sessionSynchronization);
|
|
||||||
|
|
||||||
if (session == null) {
|
|
||||||
return StringUtils.hasText(dbName) ? factory.getDb(dbName) : factory.getDb();
|
|
||||||
}
|
|
||||||
|
|
||||||
MongoDbFactory factoryToUse = factory.withSession(session);
|
|
||||||
return StringUtils.hasText(dbName) ? factoryToUse.getDb(dbName) : factoryToUse.getDb();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the {@link MongoDbFactory} is actually bound to a {@link ClientSession} that has an active transaction, or
|
|
||||||
* if a {@link TransactionSynchronization} has been registered for the {@link MongoDbFactory resource} and if the
|
|
||||||
* associated {@link ClientSession} has an {@link ClientSession#hasActiveTransaction() active transaction}.
|
|
||||||
*
|
|
||||||
* @param dbFactory the resource to check transactions for. Must not be {@literal null}.
|
|
||||||
* @return {@literal true} if the factory has an ongoing transaction.
|
|
||||||
* @since 2.1.3
|
|
||||||
*/
|
|
||||||
public static boolean isTransactionActive(MongoDbFactory dbFactory) {
|
|
||||||
|
|
||||||
if (dbFactory.isTransactionActive()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
MongoResourceHolder resourceHolder = (MongoResourceHolder) TransactionSynchronizationManager.getResource(dbFactory);
|
|
||||||
return resourceHolder != null && resourceHolder.hasActiveTransaction();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private static ClientSession doGetSession(MongoDbFactory dbFactory, SessionSynchronization sessionSynchronization) {
|
|
||||||
|
|
||||||
MongoResourceHolder resourceHolder = (MongoResourceHolder) TransactionSynchronizationManager.getResource(dbFactory);
|
|
||||||
|
|
||||||
// check for native MongoDB transaction
|
|
||||||
if (resourceHolder != null && (resourceHolder.hasSession() || resourceHolder.isSynchronizedWithTransaction())) {
|
|
||||||
|
|
||||||
if (!resourceHolder.hasSession()) {
|
|
||||||
resourceHolder.setSession(createClientSession(dbFactory));
|
|
||||||
}
|
|
||||||
|
|
||||||
return resourceHolder.getSession();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SessionSynchronization.ON_ACTUAL_TRANSACTION.equals(sessionSynchronization)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// init a non native MongoDB transaction by registering a MongoSessionSynchronization
|
|
||||||
|
|
||||||
resourceHolder = new MongoResourceHolder(createClientSession(dbFactory), dbFactory);
|
|
||||||
resourceHolder.getRequiredSession().startTransaction();
|
|
||||||
|
|
||||||
TransactionSynchronizationManager
|
|
||||||
.registerSynchronization(new MongoSessionSynchronization(resourceHolder, dbFactory));
|
|
||||||
resourceHolder.setSynchronizedWithTransaction(true);
|
|
||||||
TransactionSynchronizationManager.bindResource(dbFactory, resourceHolder);
|
|
||||||
|
|
||||||
return resourceHolder.getSession();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ClientSession createClientSession(MongoDbFactory dbFactory) {
|
|
||||||
return dbFactory.getSession(ClientSessionOptions.builder().causallyConsistent(true).build());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MongoDB specific {@link ResourceHolderSynchronization} for resource cleanup at the end of a transaction when
|
|
||||||
* participating in a non-native MongoDB transaction, such as a Jta or JDBC transaction.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 2.1
|
|
||||||
*/
|
|
||||||
private static class MongoSessionSynchronization extends ResourceHolderSynchronization<MongoResourceHolder, Object> {
|
|
||||||
|
|
||||||
private final MongoResourceHolder resourceHolder;
|
|
||||||
|
|
||||||
MongoSessionSynchronization(MongoResourceHolder resourceHolder, MongoDbFactory dbFactory) {
|
|
||||||
|
|
||||||
super(resourceHolder, dbFactory);
|
|
||||||
this.resourceHolder = resourceHolder;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.transaction.support.ResourceHolderSynchronization#shouldReleaseBeforeCompletion()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected boolean shouldReleaseBeforeCompletion() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.transaction.support.ResourceHolderSynchronization#processResourceAfterCommit(java.lang.Object)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected void processResourceAfterCommit(MongoResourceHolder resourceHolder) {
|
|
||||||
|
|
||||||
if (resourceHolder.hasActiveTransaction()) {
|
|
||||||
resourceHolder.getRequiredSession().commitTransaction();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.transaction.support.ResourceHolderSynchronization#afterCompletion(int)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void afterCompletion(int status) {
|
|
||||||
|
|
||||||
if (status == TransactionSynchronization.STATUS_ROLLED_BACK && this.resourceHolder.hasActiveTransaction()) {
|
|
||||||
resourceHolder.getRequiredSession().abortTransaction();
|
|
||||||
}
|
|
||||||
|
|
||||||
super.afterCompletion(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.transaction.support.ResourceHolderSynchronization#releaseResource(java.lang.Object, java.lang.Object)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected void releaseResource(MongoResourceHolder resourceHolder, Object resourceKey) {
|
|
||||||
|
|
||||||
if (resourceHolder.hasActiveSession()) {
|
|
||||||
resourceHolder.getRequiredSession().close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -15,32 +15,27 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.mongodb;
|
package org.springframework.data.mongodb;
|
||||||
|
|
||||||
import org.bson.codecs.configuration.CodecRegistry;
|
|
||||||
import org.springframework.dao.DataAccessException;
|
import org.springframework.dao.DataAccessException;
|
||||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||||
import org.springframework.data.mongodb.core.MongoExceptionTranslator;
|
import org.springframework.data.mongodb.core.MongoExceptionTranslator;
|
||||||
|
|
||||||
import com.mongodb.ClientSessionOptions;
|
|
||||||
import com.mongodb.DB;
|
import com.mongodb.DB;
|
||||||
import com.mongodb.client.ClientSession;
|
|
||||||
import com.mongodb.client.MongoDatabase;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for factories creating {@link MongoDatabase} instances.
|
* Interface for factories creating {@link DB} instances.
|
||||||
*
|
*
|
||||||
* @author Mark Pollack
|
* @author Mark Pollack
|
||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
* @author Christoph Strobl
|
|
||||||
*/
|
*/
|
||||||
public interface MongoDbFactory extends CodecRegistryProvider, MongoSessionProvider {
|
public interface MongoDbFactory {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a default {@link MongoDatabase} instance.
|
* Creates a default {@link DB} instance.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* @throws DataAccessException
|
* @throws DataAccessException
|
||||||
*/
|
*/
|
||||||
MongoDatabase getDb() throws DataAccessException;
|
DB getDb() throws DataAccessException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@link DB} instance to access the database with the given name.
|
* Creates a {@link DB} instance to access the database with the given name.
|
||||||
@@ -49,7 +44,7 @@ public interface MongoDbFactory extends CodecRegistryProvider, MongoSessionProvi
|
|||||||
* @return
|
* @return
|
||||||
* @throws DataAccessException
|
* @throws DataAccessException
|
||||||
*/
|
*/
|
||||||
MongoDatabase getDb(String dbName) throws DataAccessException;
|
DB getDb(String dbName) throws DataAccessException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exposes a shared {@link MongoExceptionTranslator}.
|
* Exposes a shared {@link MongoExceptionTranslator}.
|
||||||
@@ -57,66 +52,4 @@ public interface MongoDbFactory extends CodecRegistryProvider, MongoSessionProvi
|
|||||||
* @return will never be {@literal null}.
|
* @return will never be {@literal null}.
|
||||||
*/
|
*/
|
||||||
PersistenceExceptionTranslator getExceptionTranslator();
|
PersistenceExceptionTranslator getExceptionTranslator();
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the legacy database entry point. Please consider {@link #getDb()} instead.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* @deprecated since 2.1, use {@link #getDb()}. This method will be removed with a future version as it works only
|
|
||||||
* with the legacy MongoDB driver.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
DB getLegacyDb();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the underlying {@link CodecRegistry} used by the MongoDB Java driver.
|
|
||||||
*
|
|
||||||
* @return never {@literal null}.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
default CodecRegistry getCodecRegistry() {
|
|
||||||
return getDb().getCodecRegistry();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain a {@link ClientSession} for given ClientSessionOptions.
|
|
||||||
*
|
|
||||||
* @param options must not be {@literal null}.
|
|
||||||
* @return never {@literal null}.
|
|
||||||
* @since 2.1
|
|
||||||
*/
|
|
||||||
ClientSession getSession(ClientSessionOptions options);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain a {@link ClientSession} bound instance of {@link MongoDbFactory} returning {@link MongoDatabase} instances
|
|
||||||
* that are aware and bound to a new session with given {@link ClientSessionOptions options}.
|
|
||||||
*
|
|
||||||
* @param options must not be {@literal null}.
|
|
||||||
* @return never {@literal null}.
|
|
||||||
* @since 2.1
|
|
||||||
*/
|
|
||||||
default MongoDbFactory withSession(ClientSessionOptions options) {
|
|
||||||
return withSession(getSession(options));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain a {@link ClientSession} bound instance of {@link MongoDbFactory} returning {@link MongoDatabase} instances
|
|
||||||
* that are aware and bound to the given session.
|
|
||||||
*
|
|
||||||
* @param session must not be {@literal null}.
|
|
||||||
* @return never {@literal null}.
|
|
||||||
* @since 2.1
|
|
||||||
*/
|
|
||||||
MongoDbFactory withSession(ClientSession session);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns if the given {@link MongoDbFactory} is bound to a {@link ClientSession} that has an
|
|
||||||
* {@link ClientSession#hasActiveTransaction() active transaction}.
|
|
||||||
*
|
|
||||||
* @return {@literal true} if there's an active transaction, {@literal false} otherwise.
|
|
||||||
* @since 2.1.3
|
|
||||||
*/
|
|
||||||
default boolean isTransactionActive() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,153 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
import org.springframework.lang.Nullable;
|
|
||||||
import org.springframework.transaction.TransactionDefinition;
|
|
||||||
import org.springframework.transaction.support.ResourceHolderSupport;
|
|
||||||
|
|
||||||
import com.mongodb.client.ClientSession;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MongoDB specific {@link ResourceHolderSupport resource holder}, wrapping a {@link ClientSession}.
|
|
||||||
* {@link MongoTransactionManager} binds instances of this class to the thread.
|
|
||||||
* <p />
|
|
||||||
* <strong>Note:</strong> Intended for internal usage only.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @author Mark Paluch
|
|
||||||
* @since 2.1
|
|
||||||
* @see MongoTransactionManager
|
|
||||||
* @see org.springframework.data.mongodb.core.MongoTemplate
|
|
||||||
*/
|
|
||||||
class MongoResourceHolder extends ResourceHolderSupport {
|
|
||||||
|
|
||||||
private @Nullable ClientSession session;
|
|
||||||
private MongoDbFactory dbFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new {@link MongoResourceHolder} for a given {@link ClientSession session}.
|
|
||||||
*
|
|
||||||
* @param session the associated {@link ClientSession}. Can be {@literal null}.
|
|
||||||
* @param dbFactory the associated {@link MongoDbFactory}. must not be {@literal null}.
|
|
||||||
*/
|
|
||||||
MongoResourceHolder(@Nullable ClientSession session, MongoDbFactory dbFactory) {
|
|
||||||
|
|
||||||
this.session = session;
|
|
||||||
this.dbFactory = dbFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the associated {@link ClientSession}. Can be {@literal null}.
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
ClientSession getSession() {
|
|
||||||
return session;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the required associated {@link ClientSession}.
|
|
||||||
* @throws IllegalStateException if no {@link ClientSession} is associated with this {@link MongoResourceHolder}.
|
|
||||||
* @since 2.1.3
|
|
||||||
*/
|
|
||||||
ClientSession getRequiredSession() {
|
|
||||||
|
|
||||||
ClientSession session = getSession();
|
|
||||||
|
|
||||||
if (session == null) {
|
|
||||||
throw new IllegalStateException("No session available!");
|
|
||||||
}
|
|
||||||
|
|
||||||
return session;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the associated {@link MongoDbFactory}.
|
|
||||||
*/
|
|
||||||
public MongoDbFactory getDbFactory() {
|
|
||||||
return dbFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the {@link ClientSession} to guard.
|
|
||||||
*
|
|
||||||
* @param session can be {@literal null}.
|
|
||||||
*/
|
|
||||||
public void setSession(@Nullable ClientSession session) {
|
|
||||||
this.session = session;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Only set the timeout if it does not match the {@link TransactionDefinition#TIMEOUT_DEFAULT default timeout}.
|
|
||||||
*
|
|
||||||
* @param seconds
|
|
||||||
*/
|
|
||||||
void setTimeoutIfNotDefaulted(int seconds) {
|
|
||||||
|
|
||||||
if (seconds != TransactionDefinition.TIMEOUT_DEFAULT) {
|
|
||||||
setTimeoutInSeconds(seconds);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {@literal true} if session is not {@literal null}.
|
|
||||||
*/
|
|
||||||
boolean hasSession() {
|
|
||||||
return session != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {@literal true} if the session is active and has not been closed.
|
|
||||||
*/
|
|
||||||
boolean hasActiveSession() {
|
|
||||||
|
|
||||||
if (!hasSession()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return hasServerSession() && !getRequiredSession().getServerSession().isClosed();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {@literal true} if the session has an active transaction.
|
|
||||||
* @since 2.1.3
|
|
||||||
* @see #hasActiveSession()
|
|
||||||
*/
|
|
||||||
boolean hasActiveTransaction() {
|
|
||||||
|
|
||||||
if (!hasActiveSession()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return getRequiredSession().hasActiveTransaction();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {@literal true} if the {@link ClientSession} has a {@link com.mongodb.session.ServerSession} associated
|
|
||||||
* that is accessible via {@link ClientSession#getServerSession()}.
|
|
||||||
*/
|
|
||||||
boolean hasServerSession() {
|
|
||||||
|
|
||||||
try {
|
|
||||||
return getRequiredSession().getServerSession() != null;
|
|
||||||
} catch (IllegalStateException serverSessionClosed) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
import com.mongodb.ClientSessionOptions;
|
|
||||||
import com.mongodb.client.ClientSession;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A simple interface for obtaining a {@link ClientSession} to be consumed by
|
|
||||||
* {@link org.springframework.data.mongodb.core.MongoOperations} and MongoDB native operations that support causal
|
|
||||||
* consistency and transactions.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @currentRead Shadow's Edge - Brent Weeks
|
|
||||||
* @since 2.1
|
|
||||||
*/
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface MongoSessionProvider {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain a {@link ClientSession} with with given options.
|
|
||||||
*
|
|
||||||
* @param options must not be {@literal null}.
|
|
||||||
* @return never {@literal null}.
|
|
||||||
* @throws org.springframework.dao.DataAccessException
|
|
||||||
*/
|
|
||||||
ClientSession getSession(ClientSessionOptions options);
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
import org.springframework.lang.Nullable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A specific {@link ClientSessionException} related to issues with a transaction such as aborted or non existing
|
|
||||||
* transactions.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 2.1
|
|
||||||
*/
|
|
||||||
public class MongoTransactionException extends ClientSessionException {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for {@link MongoTransactionException}.
|
|
||||||
*
|
|
||||||
* @param msg the detail message. Must not be {@literal null}.
|
|
||||||
*/
|
|
||||||
public MongoTransactionException(String msg) {
|
|
||||||
super(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for {@link ClientSessionException}.
|
|
||||||
*
|
|
||||||
* @param msg the detail message. Can be {@literal null}.
|
|
||||||
* @param cause the root cause. Can be {@literal null}.
|
|
||||||
*/
|
|
||||||
public MongoTransactionException(@Nullable String msg, @Nullable Throwable cause) {
|
|
||||||
super(msg, cause);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,526 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
|
||||||
import org.springframework.lang.Nullable;
|
|
||||||
import org.springframework.transaction.TransactionDefinition;
|
|
||||||
import org.springframework.transaction.TransactionException;
|
|
||||||
import org.springframework.transaction.TransactionSystemException;
|
|
||||||
import org.springframework.transaction.support.AbstractPlatformTransactionManager;
|
|
||||||
import org.springframework.transaction.support.DefaultTransactionStatus;
|
|
||||||
import org.springframework.transaction.support.ResourceTransactionManager;
|
|
||||||
import org.springframework.transaction.support.SmartTransactionObject;
|
|
||||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
|
||||||
import org.springframework.transaction.support.TransactionSynchronizationUtils;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.util.ClassUtils;
|
|
||||||
|
|
||||||
import com.mongodb.ClientSessionOptions;
|
|
||||||
import com.mongodb.MongoException;
|
|
||||||
import com.mongodb.TransactionOptions;
|
|
||||||
import com.mongodb.client.ClientSession;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A {@link org.springframework.transaction.PlatformTransactionManager} implementation that manages
|
|
||||||
* {@link ClientSession} based transactions for a single {@link MongoDbFactory}.
|
|
||||||
* <p />
|
|
||||||
* Binds a {@link ClientSession} from the specified {@link MongoDbFactory} to the thread.
|
|
||||||
* <p />
|
|
||||||
* {@link TransactionDefinition#isReadOnly() Readonly} transactions operate on a {@link ClientSession} and enable causal
|
|
||||||
* consistency, and also {@link ClientSession#startTransaction() start}, {@link ClientSession#commitTransaction()
|
|
||||||
* commit} or {@link ClientSession#abortTransaction() abort} a transaction.
|
|
||||||
* <p />
|
|
||||||
* Application code is required to retrieve the {@link com.mongodb.client.MongoDatabase} via
|
|
||||||
* {@link MongoDatabaseUtils#getDatabase(MongoDbFactory)} instead of a standard {@link MongoDbFactory#getDb()} call.
|
|
||||||
* Spring classes such as {@link org.springframework.data.mongodb.core.MongoTemplate} use this strategy implicitly.
|
|
||||||
* <p />
|
|
||||||
* By default failure of a {@literal commit} operation raises a {@link TransactionSystemException}. One may override
|
|
||||||
* {@link #doCommit(MongoTransactionObject)} to implement the
|
|
||||||
* <a href="https://docs.mongodb.com/manual/core/transactions/#retry-commit-operation">Retry Commit Operation</a>
|
|
||||||
* behavior as outlined in the MongoDB reference manual.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @author Mark Paluch
|
|
||||||
* @currentRead Shadow's Edge - Brent Weeks
|
|
||||||
* @since 2.1
|
|
||||||
* @see <a href="https://www.mongodb.com/transactions">MongoDB Transaction Documentation</a>
|
|
||||||
* @see MongoDatabaseUtils#getDatabase(MongoDbFactory, SessionSynchronization)
|
|
||||||
*/
|
|
||||||
public class MongoTransactionManager extends AbstractPlatformTransactionManager
|
|
||||||
implements ResourceTransactionManager, InitializingBean {
|
|
||||||
|
|
||||||
private @Nullable MongoDbFactory dbFactory;
|
|
||||||
private @Nullable TransactionOptions options;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new {@link MongoTransactionManager} for bean-style usage.
|
|
||||||
* <p />
|
|
||||||
* <strong>Note:</strong>The {@link MongoDbFactory db factory} has to be {@link #setDbFactory(MongoDbFactory) set}
|
|
||||||
* before using the instance. Use this constructor to prepare a {@link MongoTransactionManager} via a
|
|
||||||
* {@link org.springframework.beans.factory.BeanFactory}.
|
|
||||||
* <p />
|
|
||||||
* Optionally it is possible to set default {@link TransactionOptions transaction options} defining
|
|
||||||
* {@link com.mongodb.ReadConcern} and {@link com.mongodb.WriteConcern}.
|
|
||||||
*
|
|
||||||
* @see #setDbFactory(MongoDbFactory)
|
|
||||||
* @see #setTransactionSynchronization(int)
|
|
||||||
*/
|
|
||||||
public MongoTransactionManager() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new {@link MongoTransactionManager} obtaining sessions from the given {@link MongoDbFactory}.
|
|
||||||
*
|
|
||||||
* @param dbFactory must not be {@literal null}.
|
|
||||||
*/
|
|
||||||
public MongoTransactionManager(MongoDbFactory dbFactory) {
|
|
||||||
this(dbFactory, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new {@link MongoTransactionManager} obtaining sessions from the given {@link MongoDbFactory} applying the
|
|
||||||
* given {@link TransactionOptions options}, if present, when starting a new transaction.
|
|
||||||
*
|
|
||||||
* @param dbFactory must not be {@literal null}.
|
|
||||||
* @param options can be {@literal null}.
|
|
||||||
*/
|
|
||||||
public MongoTransactionManager(MongoDbFactory dbFactory, @Nullable TransactionOptions options) {
|
|
||||||
|
|
||||||
Assert.notNull(dbFactory, "DbFactory must not be null!");
|
|
||||||
|
|
||||||
this.dbFactory = dbFactory;
|
|
||||||
this.options = options;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* org.springframework.transaction.support.AbstractPlatformTransactionManager#doGetTransaction()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected Object doGetTransaction() throws TransactionException {
|
|
||||||
|
|
||||||
MongoResourceHolder resourceHolder = (MongoResourceHolder) TransactionSynchronizationManager
|
|
||||||
.getResource(getRequiredDbFactory());
|
|
||||||
return new MongoTransactionObject(resourceHolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* org.springframework.transaction.support.AbstractPlatformTransactionManager#isExistingTransaction(java.lang.Object)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected boolean isExistingTransaction(Object transaction) throws TransactionException {
|
|
||||||
return extractMongoTransaction(transaction).hasResourceHolder();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* org.springframework.transaction.support.AbstractPlatformTransactionManager#doBegin(java.lang.Object, org.springframework.transaction.TransactionDefinition)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected void doBegin(Object transaction, TransactionDefinition definition) throws TransactionException {
|
|
||||||
|
|
||||||
MongoTransactionObject mongoTransactionObject = extractMongoTransaction(transaction);
|
|
||||||
|
|
||||||
MongoResourceHolder resourceHolder = newResourceHolder(definition,
|
|
||||||
ClientSessionOptions.builder().causallyConsistent(true).build());
|
|
||||||
mongoTransactionObject.setResourceHolder(resourceHolder);
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger
|
|
||||||
.debug(String.format("About to start transaction for session %s.", debugString(resourceHolder.getSession())));
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
mongoTransactionObject.startTransaction(options);
|
|
||||||
} catch (MongoException ex) {
|
|
||||||
throw new TransactionSystemException(String.format("Could not start Mongo transaction for session %s.",
|
|
||||||
debugString(mongoTransactionObject.getSession())), ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug(String.format("Started transaction for session %s.", debugString(resourceHolder.getSession())));
|
|
||||||
}
|
|
||||||
|
|
||||||
resourceHolder.setSynchronizedWithTransaction(true);
|
|
||||||
TransactionSynchronizationManager.bindResource(getRequiredDbFactory(), resourceHolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* org.springframework.transaction.support.AbstractPlatformTransactionManager#doSuspend(java.lang.Object)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected Object doSuspend(Object transaction) throws TransactionException {
|
|
||||||
|
|
||||||
MongoTransactionObject mongoTransactionObject = extractMongoTransaction(transaction);
|
|
||||||
mongoTransactionObject.setResourceHolder(null);
|
|
||||||
|
|
||||||
return TransactionSynchronizationManager.unbindResource(getRequiredDbFactory());
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* org.springframework.transaction.support.AbstractPlatformTransactionManager#doResume(java.lang.Object, java.lang.Object)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected void doResume(@Nullable Object transaction, Object suspendedResources) {
|
|
||||||
TransactionSynchronizationManager.bindResource(getRequiredDbFactory(), suspendedResources);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* org.springframework.transaction.support.AbstractPlatformTransactionManager#doCommit(org.springframework.transaction.support.DefaultTransactionStatus)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected final void doCommit(DefaultTransactionStatus status) throws TransactionException {
|
|
||||||
|
|
||||||
MongoTransactionObject mongoTransactionObject = extractMongoTransaction(status);
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug(String.format("About to commit transaction for session %s.",
|
|
||||||
debugString(mongoTransactionObject.getSession())));
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
doCommit(mongoTransactionObject);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
|
|
||||||
throw new TransactionSystemException(String.format("Could not commit Mongo transaction for session %s.",
|
|
||||||
debugString(mongoTransactionObject.getSession())), ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Customization hook to perform an actual commit of the given transaction.<br />
|
|
||||||
* If a commit operation encounters an error, the MongoDB driver throws a {@link MongoException} holding
|
|
||||||
* {@literal error labels}. <br />
|
|
||||||
* By default those labels are ignored, nevertheless one might check for
|
|
||||||
* {@link MongoException#UNKNOWN_TRANSACTION_COMMIT_RESULT_LABEL transient commit errors labels} and retry the the
|
|
||||||
* commit. <br />
|
|
||||||
* <code>
|
|
||||||
* <pre>
|
|
||||||
* int retries = 3;
|
|
||||||
* do {
|
|
||||||
* try {
|
|
||||||
* transactionObject.commitTransaction();
|
|
||||||
* break;
|
|
||||||
* } catch (MongoException ex) {
|
|
||||||
* if (!ex.hasErrorLabel(MongoException.UNKNOWN_TRANSACTION_COMMIT_RESULT_LABEL)) {
|
|
||||||
* throw ex;
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
* Thread.sleep(500);
|
|
||||||
* } while (--retries > 0);
|
|
||||||
* </pre>
|
|
||||||
* </code>
|
|
||||||
*
|
|
||||||
* @param transactionObject never {@literal null}.
|
|
||||||
* @throws Exception in case of transaction errors.
|
|
||||||
*/
|
|
||||||
protected void doCommit(MongoTransactionObject transactionObject) throws Exception {
|
|
||||||
transactionObject.commitTransaction();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* org.springframework.transaction.support.AbstractPlatformTransactionManager#doRollback(org.springframework.transaction.support.DefaultTransactionStatus)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected void doRollback(DefaultTransactionStatus status) throws TransactionException {
|
|
||||||
|
|
||||||
MongoTransactionObject mongoTransactionObject = extractMongoTransaction(status);
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug(String.format("About to abort transaction for session %s.",
|
|
||||||
debugString(mongoTransactionObject.getSession())));
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
mongoTransactionObject.abortTransaction();
|
|
||||||
} catch (MongoException ex) {
|
|
||||||
|
|
||||||
throw new TransactionSystemException(String.format("Could not abort Mongo transaction for session %s.",
|
|
||||||
debugString(mongoTransactionObject.getSession())), ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* org.springframework.transaction.support.AbstractPlatformTransactionManager#doSetRollbackOnly(org.springframework.transaction.support.DefaultTransactionStatus)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected void doSetRollbackOnly(DefaultTransactionStatus status) throws TransactionException {
|
|
||||||
|
|
||||||
MongoTransactionObject transactionObject = extractMongoTransaction(status);
|
|
||||||
transactionObject.getRequiredResourceHolder().setRollbackOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* org.springframework.transaction.support.AbstractPlatformTransactionManager#doCleanupAfterCompletion(java.lang.Object)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected void doCleanupAfterCompletion(Object transaction) {
|
|
||||||
|
|
||||||
Assert.isInstanceOf(MongoTransactionObject.class, transaction,
|
|
||||||
() -> String.format("Expected to find a %s but it turned out to be %s.", MongoTransactionObject.class,
|
|
||||||
transaction.getClass()));
|
|
||||||
|
|
||||||
MongoTransactionObject mongoTransactionObject = (MongoTransactionObject) transaction;
|
|
||||||
|
|
||||||
// Remove the connection holder from the thread.
|
|
||||||
TransactionSynchronizationManager.unbindResource(getRequiredDbFactory());
|
|
||||||
mongoTransactionObject.getRequiredResourceHolder().clear();
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug(String.format("About to release Session %s after transaction.",
|
|
||||||
debugString(mongoTransactionObject.getSession())));
|
|
||||||
}
|
|
||||||
|
|
||||||
mongoTransactionObject.closeSession();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the {@link MongoDbFactory} that this instance should manage transactions for.
|
|
||||||
*
|
|
||||||
* @param dbFactory must not be {@literal null}.
|
|
||||||
*/
|
|
||||||
public void setDbFactory(MongoDbFactory dbFactory) {
|
|
||||||
|
|
||||||
Assert.notNull(dbFactory, "DbFactory must not be null!");
|
|
||||||
this.dbFactory = dbFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the {@link TransactionOptions} to be applied when starting transactions.
|
|
||||||
*
|
|
||||||
* @param options can be {@literal null}.
|
|
||||||
*/
|
|
||||||
public void setOptions(@Nullable TransactionOptions options) {
|
|
||||||
this.options = options;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the {@link MongoDbFactory} that this instance manages transactions for.
|
|
||||||
*
|
|
||||||
* @return can be {@literal null}.
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public MongoDbFactory getDbFactory() {
|
|
||||||
return dbFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.transaction.support.ResourceTransactionManager#getResourceFactory()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public MongoDbFactory getResourceFactory() {
|
|
||||||
return getRequiredDbFactory();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void afterPropertiesSet() {
|
|
||||||
getRequiredDbFactory();
|
|
||||||
}
|
|
||||||
|
|
||||||
private MongoResourceHolder newResourceHolder(TransactionDefinition definition, ClientSessionOptions options) {
|
|
||||||
|
|
||||||
MongoDbFactory dbFactory = getResourceFactory();
|
|
||||||
|
|
||||||
MongoResourceHolder resourceHolder = new MongoResourceHolder(dbFactory.getSession(options), dbFactory);
|
|
||||||
resourceHolder.setTimeoutIfNotDefaulted(determineTimeout(definition));
|
|
||||||
|
|
||||||
return resourceHolder;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws IllegalStateException if {@link #dbFactory} is {@literal null}.
|
|
||||||
*/
|
|
||||||
private MongoDbFactory getRequiredDbFactory() {
|
|
||||||
|
|
||||||
Assert.state(dbFactory != null,
|
|
||||||
"MongoTransactionManager operates upon a MongoDbFactory. Did you forget to provide one? It's required.");
|
|
||||||
|
|
||||||
return dbFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static MongoTransactionObject extractMongoTransaction(Object transaction) {
|
|
||||||
|
|
||||||
Assert.isInstanceOf(MongoTransactionObject.class, transaction,
|
|
||||||
() -> String.format("Expected to find a %s but it turned out to be %s.", MongoTransactionObject.class,
|
|
||||||
transaction.getClass()));
|
|
||||||
|
|
||||||
return (MongoTransactionObject) transaction;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static MongoTransactionObject extractMongoTransaction(DefaultTransactionStatus status) {
|
|
||||||
|
|
||||||
Assert.isInstanceOf(MongoTransactionObject.class, status.getTransaction(),
|
|
||||||
() -> String.format("Expected to find a %s but it turned out to be %s.", MongoTransactionObject.class,
|
|
||||||
status.getTransaction().getClass()));
|
|
||||||
|
|
||||||
return (MongoTransactionObject) status.getTransaction();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String debugString(@Nullable ClientSession session) {
|
|
||||||
|
|
||||||
if (session == null) {
|
|
||||||
return "null";
|
|
||||||
}
|
|
||||||
|
|
||||||
String debugString = String.format("[%s@%s ", ClassUtils.getShortName(session.getClass()),
|
|
||||||
Integer.toHexString(session.hashCode()));
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (session.getServerSession() != null) {
|
|
||||||
debugString += String.format("id = %s, ", session.getServerSession().getIdentifier());
|
|
||||||
debugString += String.format("causallyConsistent = %s, ", session.isCausallyConsistent());
|
|
||||||
debugString += String.format("txActive = %s, ", session.hasActiveTransaction());
|
|
||||||
debugString += String.format("txNumber = %d, ", session.getServerSession().getTransactionNumber());
|
|
||||||
debugString += String.format("closed = %d, ", session.getServerSession().isClosed());
|
|
||||||
debugString += String.format("clusterTime = %s", session.getClusterTime());
|
|
||||||
} else {
|
|
||||||
debugString += "id = n/a";
|
|
||||||
debugString += String.format("causallyConsistent = %s, ", session.isCausallyConsistent());
|
|
||||||
debugString += String.format("txActive = %s, ", session.hasActiveTransaction());
|
|
||||||
debugString += String.format("clusterTime = %s", session.getClusterTime());
|
|
||||||
}
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
debugString += String.format("error = %s", e.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
debugString += "]";
|
|
||||||
|
|
||||||
return debugString;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MongoDB specific transaction object, representing a {@link MongoResourceHolder}. Used as transaction object by
|
|
||||||
* {@link MongoTransactionManager}.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @author Mark Paluch
|
|
||||||
* @since 2.1
|
|
||||||
* @see MongoResourceHolder
|
|
||||||
*/
|
|
||||||
protected static class MongoTransactionObject implements SmartTransactionObject {
|
|
||||||
|
|
||||||
private @Nullable MongoResourceHolder resourceHolder;
|
|
||||||
|
|
||||||
MongoTransactionObject(@Nullable MongoResourceHolder resourceHolder) {
|
|
||||||
this.resourceHolder = resourceHolder;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the {@link MongoResourceHolder}.
|
|
||||||
*
|
|
||||||
* @param resourceHolder can be {@literal null}.
|
|
||||||
*/
|
|
||||||
void setResourceHolder(@Nullable MongoResourceHolder resourceHolder) {
|
|
||||||
this.resourceHolder = resourceHolder;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {@literal true} if a {@link MongoResourceHolder} is set.
|
|
||||||
*/
|
|
||||||
final boolean hasResourceHolder() {
|
|
||||||
return resourceHolder != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start a MongoDB transaction optionally given {@link TransactionOptions}.
|
|
||||||
*
|
|
||||||
* @param options can be {@literal null}
|
|
||||||
*/
|
|
||||||
void startTransaction(@Nullable TransactionOptions options) {
|
|
||||||
|
|
||||||
ClientSession session = getRequiredSession();
|
|
||||||
if (options != null) {
|
|
||||||
session.startTransaction(options);
|
|
||||||
} else {
|
|
||||||
session.startTransaction();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Commit the transaction.
|
|
||||||
*/
|
|
||||||
public void commitTransaction() {
|
|
||||||
getRequiredSession().commitTransaction();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Rollback (abort) the transaction.
|
|
||||||
*/
|
|
||||||
public void abortTransaction() {
|
|
||||||
getRequiredSession().abortTransaction();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close a {@link ClientSession} without regard to its transactional state.
|
|
||||||
*/
|
|
||||||
void closeSession() {
|
|
||||||
|
|
||||||
ClientSession session = getRequiredSession();
|
|
||||||
if (session.getServerSession() != null && !session.getServerSession().isClosed()) {
|
|
||||||
session.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public ClientSession getSession() {
|
|
||||||
return resourceHolder != null ? resourceHolder.getSession() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private MongoResourceHolder getRequiredResourceHolder() {
|
|
||||||
|
|
||||||
Assert.state(resourceHolder != null, "MongoResourceHolder is required but not present. o_O");
|
|
||||||
return resourceHolder;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ClientSession getRequiredSession() {
|
|
||||||
|
|
||||||
ClientSession session = getSession();
|
|
||||||
Assert.state(session != null, "A Session is required but it turned out to be null.");
|
|
||||||
return session;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.transaction.support.SmartTransactionObject#isRollbackOnly()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean isRollbackOnly() {
|
|
||||||
return this.resourceHolder != null && this.resourceHolder.isRollbackOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.transaction.support.SmartTransactionObject#flush()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void flush() {
|
|
||||||
TransactionSynchronizationUtils.triggerFlush();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.data.mongodb;
|
|
||||||
|
|
||||||
import reactor.core.publisher.Mono;
|
|
||||||
|
|
||||||
import org.bson.codecs.configuration.CodecRegistry;
|
|
||||||
import org.springframework.dao.DataAccessException;
|
|
||||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
|
||||||
import org.springframework.data.mongodb.core.MongoExceptionTranslator;
|
|
||||||
|
|
||||||
import com.mongodb.ClientSessionOptions;
|
|
||||||
import com.mongodb.reactivestreams.client.ClientSession;
|
|
||||||
import com.mongodb.reactivestreams.client.MongoDatabase;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface for factories creating reactive {@link MongoDatabase} instances.
|
|
||||||
*
|
|
||||||
* @author Mark Paluch
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 2.0
|
|
||||||
*/
|
|
||||||
public interface ReactiveMongoDatabaseFactory extends CodecRegistryProvider {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a default {@link MongoDatabase} instance.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* @throws DataAccessException
|
|
||||||
*/
|
|
||||||
MongoDatabase getMongoDatabase() throws DataAccessException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a {@link MongoDatabase} instance to access the database with the given name.
|
|
||||||
*
|
|
||||||
* @param dbName must not be {@literal null} or empty.
|
|
||||||
* @return
|
|
||||||
* @throws DataAccessException
|
|
||||||
*/
|
|
||||||
MongoDatabase getMongoDatabase(String dbName) throws DataAccessException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exposes a shared {@link MongoExceptionTranslator}.
|
|
||||||
*
|
|
||||||
* @return will never be {@literal null}.
|
|
||||||
*/
|
|
||||||
PersistenceExceptionTranslator getExceptionTranslator();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the underlying {@link CodecRegistry} used by the reactive MongoDB Java driver.
|
|
||||||
*
|
|
||||||
* @return never {@literal null}.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
default CodecRegistry getCodecRegistry() {
|
|
||||||
return getMongoDatabase().getCodecRegistry();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain a {@link Mono} emitting a {@link ClientSession} for given {@link ClientSessionOptions options}.
|
|
||||||
*
|
|
||||||
* @param options must not be {@literal null}.
|
|
||||||
* @return never {@literal null}.
|
|
||||||
* @since 2.1
|
|
||||||
*/
|
|
||||||
Mono<ClientSession> getSession(ClientSessionOptions options);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain a {@link ClientSession} bound instance of {@link ReactiveMongoDatabaseFactory} returning
|
|
||||||
* {@link MongoDatabase} instances that are aware and bound to the given session.
|
|
||||||
*
|
|
||||||
* @param session must not be {@literal null}.
|
|
||||||
* @return never {@literal null}.
|
|
||||||
* @since 2.1
|
|
||||||
*/
|
|
||||||
ReactiveMongoDatabaseFactory withSession(ClientSession session);
|
|
||||||
}
|
|
||||||
@@ -1,215 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.lang.reflect.Proxy;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.function.BiFunction;
|
|
||||||
|
|
||||||
import org.aopalliance.intercept.MethodInterceptor;
|
|
||||||
import org.aopalliance.intercept.MethodInvocation;
|
|
||||||
import org.springframework.core.MethodClassKey;
|
|
||||||
import org.springframework.lang.Nullable;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.util.ClassUtils;
|
|
||||||
import org.springframework.util.ConcurrentReferenceHashMap;
|
|
||||||
import org.springframework.util.ReflectionUtils;
|
|
||||||
|
|
||||||
import com.mongodb.WriteConcern;
|
|
||||||
import com.mongodb.session.ClientSession;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link MethodInterceptor} implementation looking up and invoking an alternative target method having
|
|
||||||
* {@link ClientSession} as its first argument. This allows seamless integration with the existing code base.
|
|
||||||
* <p />
|
|
||||||
* The {@link MethodInterceptor} is aware of methods on {@code MongoCollection} that my return new instances of itself
|
|
||||||
* like (eg. {@link com.mongodb.reactivestreams.client.MongoCollection#withWriteConcern(WriteConcern)} and decorate them
|
|
||||||
* if not already proxied.
|
|
||||||
*
|
|
||||||
* @param <D> Type of the actual Mongo Database.
|
|
||||||
* @param <C> Type of the actual Mongo Collection.
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @author Mark Paluch
|
|
||||||
* @since 2.1
|
|
||||||
*/
|
|
||||||
public class SessionAwareMethodInterceptor<D, C> implements MethodInterceptor {
|
|
||||||
|
|
||||||
private static final MethodCache METHOD_CACHE = new MethodCache();
|
|
||||||
|
|
||||||
private final ClientSession session;
|
|
||||||
private final ClientSessionOperator collectionDecorator;
|
|
||||||
private final ClientSessionOperator databaseDecorator;
|
|
||||||
private final Object target;
|
|
||||||
private final Class<?> targetType;
|
|
||||||
private final Class<?> collectionType;
|
|
||||||
private final Class<?> databaseType;
|
|
||||||
private final Class<? extends ClientSession> sessionType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new SessionAwareMethodInterceptor for given target.
|
|
||||||
*
|
|
||||||
* @param session the {@link ClientSession} to be used on invocation.
|
|
||||||
* @param target the original target object.
|
|
||||||
* @param databaseType the MongoDB database type
|
|
||||||
* @param databaseDecorator a {@link ClientSessionOperator} used to create the proxy for an imperative / reactive
|
|
||||||
* {@code MongoDatabase}.
|
|
||||||
* @param collectionType the MongoDB collection type.
|
|
||||||
* @param collectionDecorator a {@link ClientSessionOperator} used to create the proxy for an imperative / reactive
|
|
||||||
* {@code MongoCollection}.
|
|
||||||
* @param <T> target object type.
|
|
||||||
*/
|
|
||||||
public <T> SessionAwareMethodInterceptor(ClientSession session, T target, Class<? extends ClientSession> sessionType,
|
|
||||||
Class<D> databaseType, ClientSessionOperator<D> databaseDecorator, Class<C> collectionType,
|
|
||||||
ClientSessionOperator<C> collectionDecorator) {
|
|
||||||
|
|
||||||
Assert.notNull(session, "ClientSession must not be null!");
|
|
||||||
Assert.notNull(target, "Target must not be null!");
|
|
||||||
Assert.notNull(sessionType, "SessionType must not be null!");
|
|
||||||
Assert.notNull(databaseType, "Database type must not be null!");
|
|
||||||
Assert.notNull(databaseDecorator, "Database ClientSessionOperator must not be null!");
|
|
||||||
Assert.notNull(collectionType, "Collection type must not be null!");
|
|
||||||
Assert.notNull(collectionDecorator, "Collection ClientSessionOperator must not be null!");
|
|
||||||
|
|
||||||
this.session = session;
|
|
||||||
this.target = target;
|
|
||||||
this.databaseType = ClassUtils.getUserClass(databaseType);
|
|
||||||
this.collectionType = ClassUtils.getUserClass(collectionType);
|
|
||||||
this.collectionDecorator = collectionDecorator;
|
|
||||||
this.databaseDecorator = databaseDecorator;
|
|
||||||
|
|
||||||
this.targetType = ClassUtils.isAssignable(databaseType, target.getClass()) ? databaseType : collectionType;
|
|
||||||
this.sessionType = sessionType;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.aopalliance.intercept.MethodInterceptor(org.aopalliance.intercept.MethodInvocation)
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
|
|
||||||
|
|
||||||
if (requiresDecoration(methodInvocation.getMethod())) {
|
|
||||||
|
|
||||||
Object target = methodInvocation.proceed();
|
|
||||||
if (target instanceof Proxy) {
|
|
||||||
return target;
|
|
||||||
}
|
|
||||||
|
|
||||||
return decorate(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!requiresSession(methodInvocation.getMethod())) {
|
|
||||||
return methodInvocation.proceed();
|
|
||||||
}
|
|
||||||
|
|
||||||
Optional<Method> targetMethod = METHOD_CACHE.lookup(methodInvocation.getMethod(), targetType, sessionType);
|
|
||||||
|
|
||||||
return !targetMethod.isPresent() ? methodInvocation.proceed()
|
|
||||||
: ReflectionUtils.invokeMethod(targetMethod.get(), target,
|
|
||||||
prependSessionToArguments(session, methodInvocation));
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean requiresDecoration(Method method) {
|
|
||||||
|
|
||||||
return ClassUtils.isAssignable(databaseType, method.getReturnType())
|
|
||||||
|| ClassUtils.isAssignable(collectionType, method.getReturnType());
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
protected Object decorate(Object target) {
|
|
||||||
|
|
||||||
return ClassUtils.isAssignable(databaseType, target.getClass()) ? databaseDecorator.apply(session, target)
|
|
||||||
: collectionDecorator.apply(session, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean requiresSession(Method method) {
|
|
||||||
|
|
||||||
if (method.getParameterCount() == 0
|
|
||||||
|| !ClassUtils.isAssignable(ClientSession.class, method.getParameterTypes()[0])) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Object[] prependSessionToArguments(ClientSession session, MethodInvocation invocation) {
|
|
||||||
|
|
||||||
Object[] args = new Object[invocation.getArguments().length + 1];
|
|
||||||
|
|
||||||
args[0] = session;
|
|
||||||
System.arraycopy(invocation.getArguments(), 0, args, 1, invocation.getArguments().length);
|
|
||||||
|
|
||||||
return args;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple {@link Method} to {@link Method} caching facility for {@link ClientSession} overloaded targets.
|
|
||||||
*
|
|
||||||
* @since 2.1
|
|
||||||
* @author Christoph Strobl
|
|
||||||
*/
|
|
||||||
static class MethodCache {
|
|
||||||
|
|
||||||
private final ConcurrentReferenceHashMap<MethodClassKey, Optional<Method>> cache = new ConcurrentReferenceHashMap<>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Lookup the target {@link Method}.
|
|
||||||
*
|
|
||||||
* @param method
|
|
||||||
* @param targetClass
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Optional<Method> lookup(Method method, Class<?> targetClass, Class<? extends ClientSession> sessionType) {
|
|
||||||
|
|
||||||
return cache.computeIfAbsent(new MethodClassKey(method, targetClass),
|
|
||||||
val -> Optional.ofNullable(findTargetWithSession(method, targetClass, sessionType)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private Method findTargetWithSession(Method sourceMethod, Class<?> targetType,
|
|
||||||
Class<? extends ClientSession> sessionType) {
|
|
||||||
|
|
||||||
Class<?>[] argTypes = sourceMethod.getParameterTypes();
|
|
||||||
Class<?>[] args = new Class<?>[argTypes.length + 1];
|
|
||||||
args[0] = sessionType;
|
|
||||||
System.arraycopy(argTypes, 0, args, 1, argTypes.length);
|
|
||||||
|
|
||||||
return ReflectionUtils.findMethod(targetType, sourceMethod.getName(), args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check whether the cache contains an entry for {@link Method} and {@link Class}.
|
|
||||||
*
|
|
||||||
* @param method
|
|
||||||
* @param targetClass
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
boolean contains(Method method, Class<?> targetClass) {
|
|
||||||
return cache.containsKey(new MethodClassKey(method, targetClass));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents an operation upon two operands of the same type, producing a result of the same type as the operands
|
|
||||||
* accepting {@link ClientSession}. This is a specialization of {@link BiFunction} for the case where the operands and
|
|
||||||
* the result are all of the same type.
|
|
||||||
*
|
|
||||||
* @param <T> the type of the operands and result of the operator
|
|
||||||
*/
|
|
||||||
public interface ClientSessionOperator<T> extends BiFunction<ClientSession, T, T> {}
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link SessionSynchronization} is used along with {@link org.springframework.data.mongodb.core.MongoTemplate} to
|
|
||||||
* define in which type of transactions to participate if any.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @author Mark Paluch
|
|
||||||
* @since 2.1
|
|
||||||
*/
|
|
||||||
public enum SessionSynchronization {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Synchronize with any transaction even with empty transactions and initiate a MongoDB transaction when doing so by
|
|
||||||
* registering a MongoDB specific {@link org.springframework.transaction.support.ResourceHolderSynchronization}.
|
|
||||||
*/
|
|
||||||
ALWAYS,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Synchronize with native MongoDB transactions initiated via {@link MongoTransactionManager}.
|
|
||||||
*/
|
|
||||||
ON_ACTUAL_TRANSACTION;
|
|
||||||
}
|
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
|||||||
@@ -1,111 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* 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.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.data.mongodb.MongoDbFactory;
|
|
||||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
|
||||||
import org.springframework.data.mongodb.core.SimpleMongoClientDbFactory;
|
|
||||||
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
|
|
||||||
import org.springframework.data.mongodb.core.convert.DbRefResolver;
|
|
||||||
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
|
|
||||||
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
|
|
||||||
import org.springframework.data.mongodb.core.mapping.Document;
|
|
||||||
import org.springframework.lang.Nullable;
|
|
||||||
|
|
||||||
import com.mongodb.client.MongoClient;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base class for Spring Data MongoDB configuration using JavaConfig with {@link com.mongodb.client.MongoClient}.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 2.1
|
|
||||||
* @see MongoConfigurationSupport
|
|
||||||
* @see AbstractMongoConfiguration
|
|
||||||
*/
|
|
||||||
@Configuration
|
|
||||||
public abstract class AbstractMongoClientConfiguration extends MongoConfigurationSupport {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the {@link MongoClient} instance to connect to. Annotate with {@link Bean} in case you want to expose a
|
|
||||||
* {@link MongoClient} instance to the {@link org.springframework.context.ApplicationContext}.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public abstract MongoClient mongoClient();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a {@link MongoTemplate}.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public MongoTemplate mongoTemplate() throws Exception {
|
|
||||||
return new MongoTemplate(mongoDbFactory(), mappingMongoConverter());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a {@link SimpleMongoDbFactory} to be used by the {@link MongoTemplate}. Will use the {@link MongoClient}
|
|
||||||
* instance configured in {@link #mongoClient()}.
|
|
||||||
*
|
|
||||||
* @see #mongoClient()
|
|
||||||
* @see #mongoTemplate()
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public MongoDbFactory mongoDbFactory() {
|
|
||||||
return new SimpleMongoClientDbFactory(mongoClient(), getDatabaseName());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the base package to scan for mapped {@link Document}s. Will return the package name of the configuration
|
|
||||||
* class' (the concrete class, not this one here) by default. So if you have a {@code com.acme.AppConfig} extending
|
|
||||||
* {@link AbstractMongoClientConfiguration} the base package will be considered {@code com.acme} unless the method is
|
|
||||||
* overridden to implement alternate behavior.
|
|
||||||
*
|
|
||||||
* @return the base package to scan for mapped {@link Document} classes or {@literal null} to not enable scanning for
|
|
||||||
* entities.
|
|
||||||
* @deprecated use {@link #getMappingBasePackages()} instead.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
@Nullable
|
|
||||||
protected String getMappingBasePackage() {
|
|
||||||
|
|
||||||
Package mappingBasePackage = getClass().getPackage();
|
|
||||||
return mappingBasePackage == null ? null : mappingBasePackage.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a {@link MappingMongoConverter} using the configured {@link #mongoDbFactory()} and
|
|
||||||
* {@link #mongoMappingContext()}. Will get {@link #customConversions()} applied.
|
|
||||||
*
|
|
||||||
* @see #customConversions()
|
|
||||||
* @see #mongoMappingContext()
|
|
||||||
* @see #mongoDbFactory()
|
|
||||||
* @return
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public MappingMongoConverter mappingMongoConverter() throws Exception {
|
|
||||||
|
|
||||||
DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory());
|
|
||||||
MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, mongoMappingContext());
|
|
||||||
converter.setCustomConversions(customConversions());
|
|
||||||
|
|
||||||
return converter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -15,49 +15,86 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.mongodb.config;
|
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.Bean;
|
||||||
|
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
||||||
import org.springframework.context.annotation.Configuration;
|
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.MongoDbFactory;
|
||||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||||
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
|
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.DbRefResolver;
|
||||||
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
|
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
|
||||||
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
|
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
|
||||||
import org.springframework.data.mongodb.core.mapping.Document;
|
import org.springframework.data.mongodb.core.mapping.Document;
|
||||||
import org.springframework.lang.Nullable;
|
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;
|
import com.mongodb.MongoClient;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for Spring Data MongoDB configuration using JavaConfig with {@link com.mongodb.MongoClient}.
|
* Base class for Spring Data MongoDB configuration using JavaConfig.
|
||||||
* <p />
|
*
|
||||||
* <strong>INFO:</strong>In case you want to use {@link com.mongodb.client.MongoClients} for configuration please refer
|
|
||||||
* to {@link AbstractMongoClientConfiguration}.
|
|
||||||
*
|
|
||||||
* @author Mark Pollack
|
* @author Mark Pollack
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
* @author Ryan Tenney
|
* @author Ryan Tenney
|
||||||
* @author Christoph Strobl
|
* @author Christoph Strobl
|
||||||
* @author Mark Paluch
|
|
||||||
* @see MongoConfigurationSupport
|
|
||||||
* @see AbstractMongoClientConfiguration
|
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
public abstract class AbstractMongoConfiguration extends MongoConfigurationSupport {
|
public abstract class AbstractMongoConfiguration {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the {@link MongoClient} instance to connect to. Annotate with {@link Bean} in case you want to expose a
|
* Return the name of the database to connect to.
|
||||||
* {@link MongoClient} instance to the {@link org.springframework.context.ApplicationContext}.
|
*
|
||||||
*
|
* @return must not be {@literal null}.
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public abstract MongoClient mongoClient();
|
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}.
|
* Creates a {@link MongoTemplate}.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
public MongoTemplate mongoTemplate() throws Exception {
|
public MongoTemplate mongoTemplate() throws Exception {
|
||||||
@@ -65,16 +102,17 @@ public abstract class AbstractMongoConfiguration extends MongoConfigurationSuppo
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@link SimpleMongoDbFactory} to be used by the {@link MongoTemplate}. Will use the {@link MongoClient}
|
* Creates a {@link SimpleMongoDbFactory} to be used by the {@link MongoTemplate}. Will use the {@link Mongo} instance
|
||||||
* instance configured in {@link #mongoClient()}.
|
* configured in {@link #mongo()}.
|
||||||
*
|
*
|
||||||
* @see #mongoClient()
|
* @see #mongo()
|
||||||
* @see #mongoTemplate()
|
* @see #mongoTemplate()
|
||||||
* @return
|
* @return
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
public MongoDbFactory mongoDbFactory() {
|
public MongoDbFactory mongoDbFactory() throws Exception {
|
||||||
return new SimpleMongoDbFactory(mongoClient(), getDatabaseName());
|
return new SimpleMongoDbFactory(mongo(), getDatabaseName(), getUserCredentials(), getAuthenticationDatabaseName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -82,23 +120,90 @@ public abstract class AbstractMongoConfiguration extends MongoConfigurationSuppo
|
|||||||
* class' (the concrete class, not this one here) by default. So if you have a {@code com.acme.AppConfig} extending
|
* 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
|
* {@link AbstractMongoConfiguration} the base package will be considered {@code com.acme} unless the method is
|
||||||
* overridden to implement alternate behavior.
|
* overridden to implement alternate behavior.
|
||||||
*
|
*
|
||||||
* @return the base package to scan for mapped {@link Document} classes or {@literal null} to not enable scanning for
|
* @return the base package to scan for mapped {@link Document} classes or {@literal null} to not enable scanning for
|
||||||
* entities.
|
* entities.
|
||||||
* @deprecated use {@link #getMappingBasePackages()} instead.
|
* @deprecated use {@link #getMappingBasePackages()} instead.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@Nullable
|
|
||||||
protected String getMappingBasePackage() {
|
protected String getMappingBasePackage() {
|
||||||
|
|
||||||
Package mappingBasePackage = getClass().getPackage();
|
Package mappingBasePackage = getClass().getPackage();
|
||||||
return mappingBasePackage == null ? null : mappingBasePackage.getName();
|
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
|
* Creates a {@link MappingMongoConverter} using the configured {@link #mongoDbFactory()} and
|
||||||
* {@link #mongoMappingContext()}. Will get {@link #customConversions()} applied.
|
* {@link #mongoMappingContext()}. Will get {@link #customConversions()} applied.
|
||||||
*
|
*
|
||||||
* @see #customConversions()
|
* @see #customConversions()
|
||||||
* @see #mongoMappingContext()
|
* @see #mongoMappingContext()
|
||||||
* @see #mongoDbFactory()
|
* @see #mongoDbFactory()
|
||||||
@@ -115,4 +220,78 @@ public abstract class AbstractMongoConfiguration extends MongoConfigurationSuppo
|
|||||||
return converter;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,89 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.data.mongodb.config;
|
|
||||||
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory;
|
|
||||||
import org.springframework.data.mongodb.core.ReactiveMongoOperations;
|
|
||||||
import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
|
|
||||||
import org.springframework.data.mongodb.core.SimpleReactiveMongoDatabaseFactory;
|
|
||||||
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
|
|
||||||
import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver;
|
|
||||||
|
|
||||||
import com.mongodb.reactivestreams.client.MongoClient;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base class for reactive Spring Data MongoDB configuration using JavaConfig.
|
|
||||||
*
|
|
||||||
* @author Mark Paluch
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 2.0
|
|
||||||
* @see MongoConfigurationSupport
|
|
||||||
*/
|
|
||||||
@Configuration
|
|
||||||
public abstract class AbstractReactiveMongoConfiguration extends MongoConfigurationSupport {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the Reactive Streams {@link MongoClient} instance to connect to. Annotate with {@link Bean} in case you want
|
|
||||||
* to expose a {@link MongoClient} instance to the {@link org.springframework.context.ApplicationContext}.
|
|
||||||
*
|
|
||||||
* @return never {@literal null}.
|
|
||||||
*/
|
|
||||||
public abstract MongoClient reactiveMongoClient();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates {@link ReactiveMongoOperations}.
|
|
||||||
*
|
|
||||||
* @return never {@literal null}.
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public ReactiveMongoOperations reactiveMongoTemplate() throws Exception {
|
|
||||||
return new ReactiveMongoTemplate(reactiveMongoDbFactory(), mappingMongoConverter());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a {@link ReactiveMongoDatabaseFactory} to be used by the {@link ReactiveMongoOperations}. Will use the
|
|
||||||
* {@link MongoClient} instance configured in {@link #reactiveMongoClient()}.
|
|
||||||
*
|
|
||||||
* @see #reactiveMongoClient()
|
|
||||||
* @see #reactiveMongoTemplate()
|
|
||||||
* @return never {@literal null}.
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public ReactiveMongoDatabaseFactory reactiveMongoDbFactory() {
|
|
||||||
return new SimpleReactiveMongoDatabaseFactory(reactiveMongoClient(), getDatabaseName());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a {@link MappingMongoConverter} using the configured {@link #reactiveMongoDbFactory()} and
|
|
||||||
* {@link #mongoMappingContext()}. Will get {@link #customConversions()} applied.
|
|
||||||
*
|
|
||||||
* @see #customConversions()
|
|
||||||
* @see #mongoMappingContext()
|
|
||||||
* @see #reactiveMongoDbFactory()
|
|
||||||
* @return never {@literal null}.
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public MappingMongoConverter mappingMongoConverter() throws Exception {
|
|
||||||
|
|
||||||
MappingMongoConverter converter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, mongoMappingContext());
|
|
||||||
converter.setCustomConversions(customConversions());
|
|
||||||
|
|
||||||
return converter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -17,18 +17,17 @@ package org.springframework.data.mongodb.config;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Constants to declare bean names used by the namespace configuration.
|
* Constants to declare bean names used by the namespace configuration.
|
||||||
*
|
*
|
||||||
* @author Jon Brisbin
|
* @author Jon Brisbin
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Martin Baumgartner
|
* @author Martin Baumgartner
|
||||||
* @author Christoph Strobl
|
|
||||||
*/
|
*/
|
||||||
public abstract class BeanNames {
|
public abstract class BeanNames {
|
||||||
|
|
||||||
public static final String MAPPING_CONTEXT_BEAN_NAME = "mongoMappingContext";
|
public static final String MAPPING_CONTEXT_BEAN_NAME = "mongoMappingContext";
|
||||||
|
|
||||||
static final String INDEX_HELPER_BEAN_NAME = "indexCreationHelper";
|
static final String INDEX_HELPER_BEAN_NAME = "indexCreationHelper";
|
||||||
static final String MONGO_BEAN_NAME = "mongoClient";
|
static final String MONGO_BEAN_NAME = "mongo";
|
||||||
static final String DB_FACTORY_BEAN_NAME = "mongoDbFactory";
|
static final String DB_FACTORY_BEAN_NAME = "mongoDbFactory";
|
||||||
static final String VALIDATING_EVENT_LISTENER_BEAN_NAME = "validatingMongoEventListener";
|
static final String VALIDATING_EVENT_LISTENER_BEAN_NAME = "validatingMongoEventListener";
|
||||||
static final String IS_NEW_STRATEGY_FACTORY_BEAN_NAME = "isNewStrategyFactory";
|
static final String IS_NEW_STRATEGY_FACTORY_BEAN_NAME = "isNewStrategyFactory";
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -28,7 +28,7 @@ import org.springframework.data.domain.AuditorAware;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Annotation to enable auditing in MongoDB via annotation configuration.
|
* Annotation to enable auditing in MongoDB via annotation configuration.
|
||||||
*
|
*
|
||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
*/
|
*/
|
||||||
@@ -41,21 +41,21 @@ public @interface EnableMongoAuditing {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the {@link AuditorAware} bean to be used to lookup the current principal.
|
* Configures the {@link AuditorAware} bean to be used to lookup the current principal.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
String auditorAwareRef() default "";
|
String auditorAwareRef() default "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures whether the creation and modification dates are set. Defaults to {@literal true}.
|
* Configures whether the creation and modification dates are set. Defaults to {@literal true}.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
boolean setDates() default true;
|
boolean setDates() default true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures whether the entity shall be marked as modified on creation. Defaults to {@literal true}.
|
* Configures whether the entity shall be marked as modified on creation. Defaults to {@literal true}.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
boolean modifyOnCreate() default true;
|
boolean modifyOnCreate() default true;
|
||||||
@@ -63,7 +63,7 @@ public @interface EnableMongoAuditing {
|
|||||||
/**
|
/**
|
||||||
* Configures a {@link DateTimeProvider} bean name that allows customizing the {@link org.joda.time.DateTime} to be
|
* Configures a {@link DateTimeProvider} bean name that allows customizing the {@link org.joda.time.DateTime} to be
|
||||||
* used for setting creation and modification dates.
|
* used for setting creation and modification dates.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
String dateTimeProviderRef() default "";
|
String dateTimeProviderRef() default "";
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -29,7 +29,7 @@ import org.w3c.dom.Element;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link BeanDefinitionParser} to parse {@code gridFsTemplate} elements into {@link BeanDefinition}s.
|
* {@link BeanDefinitionParser} to parse {@code gridFsTemplate} elements into {@link BeanDefinition}s.
|
||||||
*
|
*
|
||||||
* @author Martin Baumgartner
|
* @author Martin Baumgartner
|
||||||
*/
|
*/
|
||||||
class GridFsTemplateParser extends AbstractBeanDefinitionParser {
|
class GridFsTemplateParser extends AbstractBeanDefinitionParser {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -53,14 +53,12 @@ import org.springframework.data.annotation.Persistent;
|
|||||||
import org.springframework.data.config.BeanComponentDefinitionBuilder;
|
import org.springframework.data.config.BeanComponentDefinitionBuilder;
|
||||||
import org.springframework.data.mapping.context.MappingContextIsNewStrategyFactory;
|
import org.springframework.data.mapping.context.MappingContextIsNewStrategyFactory;
|
||||||
import org.springframework.data.mapping.model.CamelCaseAbbreviatingFieldNamingStrategy;
|
import org.springframework.data.mapping.model.CamelCaseAbbreviatingFieldNamingStrategy;
|
||||||
|
import org.springframework.data.mongodb.core.convert.CustomConversions;
|
||||||
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
|
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
|
||||||
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
|
|
||||||
import org.springframework.data.mongodb.core.convert.QueryMapper;
|
|
||||||
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCreator;
|
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCreator;
|
||||||
import org.springframework.data.mongodb.core.mapping.Document;
|
import org.springframework.data.mongodb.core.mapping.Document;
|
||||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||||
import org.springframework.data.mongodb.core.mapping.event.ValidatingMongoEventListener;
|
import org.springframework.data.mongodb.core.mapping.event.ValidatingMongoEventListener;
|
||||||
import org.springframework.lang.Nullable;
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
@@ -69,14 +67,12 @@ import org.w3c.dom.Element;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Bean definition parser for the {@code mapping-converter} element.
|
* Bean definition parser for the {@code mapping-converter} element.
|
||||||
*
|
*
|
||||||
* @author Jon Brisbin
|
* @author Jon Brisbin
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Maciej Walkowiak
|
* @author Maciej Walkowiak
|
||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
* @author Christoph Strobl
|
* @author Christoph Strobl
|
||||||
* @author Mark Paluch
|
|
||||||
* @author Zied Yaich
|
|
||||||
*/
|
*/
|
||||||
public class MappingMongoConverterParser implements BeanDefinitionParser {
|
public class MappingMongoConverterParser implements BeanDefinitionParser {
|
||||||
|
|
||||||
@@ -124,36 +120,27 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
|
|||||||
converterBuilder.addPropertyValue("customConversions", conversionsDefinition);
|
converterBuilder.addPropertyValue("customConversions", conversionsDefinition);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!registry.containsBeanDefinition("indexOperationsProvider")) {
|
|
||||||
|
|
||||||
BeanDefinitionBuilder indexOperationsProviderBuilder = BeanDefinitionBuilder
|
|
||||||
.genericBeanDefinition("org.springframework.data.mongodb.core.DefaultIndexOperationsProvider");
|
|
||||||
indexOperationsProviderBuilder.addConstructorArgReference(dbFactoryRef);
|
|
||||||
indexOperationsProviderBuilder.addConstructorArgValue(BeanDefinitionBuilder
|
|
||||||
.genericBeanDefinition(QueryMapper.class).addConstructorArgReference(id).getBeanDefinition());
|
|
||||||
parserContext.registerBeanComponent(
|
|
||||||
new BeanComponentDefinition(indexOperationsProviderBuilder.getBeanDefinition(), "indexOperationsProvider"));
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
registry.getBeanDefinition(INDEX_HELPER_BEAN_NAME);
|
registry.getBeanDefinition(INDEX_HELPER_BEAN_NAME);
|
||||||
} catch (NoSuchBeanDefinitionException ignored) {
|
} catch (NoSuchBeanDefinitionException ignored) {
|
||||||
|
if (!StringUtils.hasText(dbFactoryRef)) {
|
||||||
|
dbFactoryRef = DB_FACTORY_BEAN_NAME;
|
||||||
|
}
|
||||||
BeanDefinitionBuilder indexHelperBuilder = BeanDefinitionBuilder
|
BeanDefinitionBuilder indexHelperBuilder = BeanDefinitionBuilder
|
||||||
.genericBeanDefinition(MongoPersistentEntityIndexCreator.class);
|
.genericBeanDefinition(MongoPersistentEntityIndexCreator.class);
|
||||||
indexHelperBuilder.addConstructorArgReference(ctxRef);
|
indexHelperBuilder.addConstructorArgReference(ctxRef);
|
||||||
indexHelperBuilder.addConstructorArgReference("indexOperationsProvider");
|
indexHelperBuilder.addConstructorArgReference(dbFactoryRef);
|
||||||
indexHelperBuilder.addDependsOn(ctxRef);
|
indexHelperBuilder.addDependsOn(ctxRef);
|
||||||
|
|
||||||
parserContext.registerBeanComponent(
|
parserContext.registerBeanComponent(new BeanComponentDefinition(indexHelperBuilder.getBeanDefinition(),
|
||||||
new BeanComponentDefinition(indexHelperBuilder.getBeanDefinition(), INDEX_HELPER_BEAN_NAME));
|
INDEX_HELPER_BEAN_NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
BeanDefinition validatingMongoEventListener = potentiallyCreateValidatingMongoEventListener(element, parserContext);
|
BeanDefinition validatingMongoEventListener = potentiallyCreateValidatingMongoEventListener(element, parserContext);
|
||||||
|
|
||||||
if (validatingMongoEventListener != null) {
|
if (validatingMongoEventListener != null) {
|
||||||
parserContext.registerBeanComponent(
|
parserContext.registerBeanComponent(new BeanComponentDefinition(validatingMongoEventListener,
|
||||||
new BeanComponentDefinition(validatingMongoEventListener, VALIDATING_EVENT_LISTENER_BEAN_NAME));
|
VALIDATING_EVENT_LISTENER_BEAN_NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
parserContext.registerBeanComponent(new BeanComponentDefinition(converterBuilder.getBeanDefinition(), id));
|
parserContext.registerBeanComponent(new BeanComponentDefinition(converterBuilder.getBeanDefinition(), id));
|
||||||
@@ -161,7 +148,6 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private BeanDefinition potentiallyCreateValidatingMongoEventListener(Element element, ParserContext parserContext) {
|
private BeanDefinition potentiallyCreateValidatingMongoEventListener(Element element, ParserContext parserContext) {
|
||||||
|
|
||||||
String disableValidation = element.getAttribute("disable-validation");
|
String disableValidation = element.getAttribute("disable-validation");
|
||||||
@@ -183,7 +169,6 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private RuntimeBeanReference getValidator(Object source, ParserContext parserContext) {
|
private RuntimeBeanReference getValidator(Object source, ParserContext parserContext) {
|
||||||
|
|
||||||
if (!JSR_303_PRESENT) {
|
if (!JSR_303_PRESENT) {
|
||||||
@@ -201,7 +186,7 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String potentiallyCreateMappingContext(Element element, ParserContext parserContext,
|
public static String potentiallyCreateMappingContext(Element element, ParserContext parserContext,
|
||||||
@Nullable BeanDefinition conversionsDefinition, @Nullable String converterId) {
|
BeanDefinition conversionsDefinition, String converterId) {
|
||||||
|
|
||||||
String ctxRef = element.getAttribute("mapping-context-ref");
|
String ctxRef = element.getAttribute("mapping-context-ref");
|
||||||
|
|
||||||
@@ -215,7 +200,7 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
|
|||||||
BeanDefinitionBuilder mappingContextBuilder = BeanDefinitionBuilder
|
BeanDefinitionBuilder mappingContextBuilder = BeanDefinitionBuilder
|
||||||
.genericBeanDefinition(MongoMappingContext.class);
|
.genericBeanDefinition(MongoMappingContext.class);
|
||||||
|
|
||||||
Set<String> classesToAdd = getInitialEntityClasses(element);
|
Set<String> classesToAdd = getInititalEntityClasses(element);
|
||||||
|
|
||||||
if (classesToAdd != null) {
|
if (classesToAdd != null) {
|
||||||
mappingContextBuilder.addPropertyValue("initialEntitySet", classesToAdd);
|
mappingContextBuilder.addPropertyValue("initialEntitySet", classesToAdd);
|
||||||
@@ -266,7 +251,6 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private BeanDefinition getCustomConversions(Element element, ParserContext parserContext) {
|
private BeanDefinition getCustomConversions(Element element, ParserContext parserContext) {
|
||||||
|
|
||||||
List<Element> customConvertersElements = DomUtils.getChildElementsByTagName(element, "custom-converters");
|
List<Element> customConvertersElements = DomUtils.getChildElementsByTagName(element, "custom-converters");
|
||||||
@@ -274,7 +258,7 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
|
|||||||
if (customConvertersElements.size() == 1) {
|
if (customConvertersElements.size() == 1) {
|
||||||
|
|
||||||
Element customerConvertersElement = customConvertersElements.get(0);
|
Element customerConvertersElement = customConvertersElements.get(0);
|
||||||
ManagedList<BeanMetadataElement> converterBeans = new ManagedList<>();
|
ManagedList<BeanMetadataElement> converterBeans = new ManagedList<BeanMetadataElement>();
|
||||||
List<Element> converterElements = DomUtils.getChildElementsByTagName(customerConvertersElement, "converter");
|
List<Element> converterElements = DomUtils.getChildElementsByTagName(customerConvertersElement, "converter");
|
||||||
|
|
||||||
if (converterElements != null) {
|
if (converterElements != null) {
|
||||||
@@ -290,10 +274,12 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
|
|||||||
provider.addExcludeFilter(new NegatingFilter(new AssignableTypeFilter(Converter.class),
|
provider.addExcludeFilter(new NegatingFilter(new AssignableTypeFilter(Converter.class),
|
||||||
new AssignableTypeFilter(GenericConverter.class)));
|
new AssignableTypeFilter(GenericConverter.class)));
|
||||||
|
|
||||||
converterBeans.addAll(provider.findCandidateComponents(packageToScan));
|
for (BeanDefinition candidate : provider.findCandidateComponents(packageToScan)) {
|
||||||
|
converterBeans.add(candidate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BeanDefinitionBuilder conversionsBuilder = BeanDefinitionBuilder.rootBeanDefinition(MongoCustomConversions.class);
|
BeanDefinitionBuilder conversionsBuilder = BeanDefinitionBuilder.rootBeanDefinition(CustomConversions.class);
|
||||||
conversionsBuilder.addConstructorArgValue(converterBeans);
|
conversionsBuilder.addConstructorArgValue(converterBeans);
|
||||||
|
|
||||||
AbstractBeanDefinition conversionsBean = conversionsBuilder.getBeanDefinition();
|
AbstractBeanDefinition conversionsBean = conversionsBuilder.getBeanDefinition();
|
||||||
@@ -307,8 +293,7 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
private static Set<String> getInititalEntityClasses(Element element) {
|
||||||
private static Set<String> getInitialEntityClasses(Element element) {
|
|
||||||
|
|
||||||
String basePackage = element.getAttribute(BASE_PACKAGE);
|
String basePackage = element.getAttribute(BASE_PACKAGE);
|
||||||
|
|
||||||
@@ -321,7 +306,7 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
|
|||||||
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Document.class));
|
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Document.class));
|
||||||
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Persistent.class));
|
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Persistent.class));
|
||||||
|
|
||||||
Set<String> classes = new ManagedSet<>();
|
Set<String> classes = new ManagedSet<String>();
|
||||||
for (BeanDefinition candidate : componentProvider.findCandidateComponents(basePackage)) {
|
for (BeanDefinition candidate : componentProvider.findCandidateComponents(basePackage)) {
|
||||||
classes.add(candidate.getBeanClassName());
|
classes.add(candidate.getBeanClassName());
|
||||||
}
|
}
|
||||||
@@ -329,7 +314,6 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
|
|||||||
return classes;
|
return classes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public BeanMetadataElement parseConverter(Element element, ParserContext parserContext) {
|
public BeanMetadataElement parseConverter(Element element, ParserContext parserContext) {
|
||||||
|
|
||||||
String converterRef = element.getAttribute("ref");
|
String converterRef = element.getAttribute("ref");
|
||||||
@@ -343,8 +327,8 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
|
|||||||
return beanDef;
|
return beanDef;
|
||||||
}
|
}
|
||||||
|
|
||||||
parserContext.getReaderContext()
|
parserContext.getReaderContext().error(
|
||||||
.error("Element <converter> must specify 'ref' or contain a bean definition for the converter", element);
|
"Element <converter> must specify 'ref' or contain a bean definition for the converter", element);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,15 +340,15 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
|
|||||||
mappingContextStrategyFactoryBuilder.addConstructorArgReference(mappingContextRef);
|
mappingContextStrategyFactoryBuilder.addConstructorArgReference(mappingContextRef);
|
||||||
|
|
||||||
BeanComponentDefinitionBuilder builder = new BeanComponentDefinitionBuilder(element, context);
|
BeanComponentDefinitionBuilder builder = new BeanComponentDefinitionBuilder(element, context);
|
||||||
context.registerBeanComponent(
|
context.registerBeanComponent(builder.getComponent(mappingContextStrategyFactoryBuilder,
|
||||||
builder.getComponent(mappingContextStrategyFactoryBuilder, IS_NEW_STRATEGY_FACTORY_BEAN_NAME));
|
IS_NEW_STRATEGY_FACTORY_BEAN_NAME));
|
||||||
|
|
||||||
return IS_NEW_STRATEGY_FACTORY_BEAN_NAME;
|
return IS_NEW_STRATEGY_FACTORY_BEAN_NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link TypeFilter} that returns {@literal false} in case any of the given delegates matches.
|
* {@link TypeFilter} that returns {@literal false} in case any of the given delegates matches.
|
||||||
*
|
*
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
*/
|
*/
|
||||||
private static class NegatingFilter implements TypeFilter {
|
private static class NegatingFilter implements TypeFilter {
|
||||||
@@ -373,22 +357,21 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link NegatingFilter} with the given delegates.
|
* Creates a new {@link NegatingFilter} with the given delegates.
|
||||||
*
|
*
|
||||||
* @param filters
|
* @param filters
|
||||||
*/
|
*/
|
||||||
public NegatingFilter(TypeFilter... filters) {
|
public NegatingFilter(TypeFilter... filters) {
|
||||||
|
|
||||||
Assert.notNull(filters, "TypeFilters must not be null");
|
Assert.notNull(filters, "TypeFilters must not be null");
|
||||||
|
|
||||||
this.delegates = new HashSet<>(Arrays.asList(filters));
|
this.delegates = new HashSet<TypeFilter>(Arrays.asList(filters));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.core.type.filter.TypeFilter#match(org.springframework.core.type.classreading.MetadataReader, org.springframework.core.type.classreading.MetadataReaderFactory)
|
* @see org.springframework.core.type.filter.TypeFilter#match(org.springframework.core.type.classreading.MetadataReader, org.springframework.core.type.classreading.MetadataReaderFactory)
|
||||||
*/
|
*/
|
||||||
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
|
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
|
||||||
throws IOException {
|
|
||||||
|
|
||||||
for (TypeFilter delegate : delegates) {
|
for (TypeFilter delegate : delegates) {
|
||||||
if (delegate.match(metadataReader, metadataReaderFactory)) {
|
if (delegate.match(metadataReader, metadataReaderFactory)) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -33,12 +33,12 @@ import org.w3c.dom.Element;
|
|||||||
/**
|
/**
|
||||||
* {@link BeanDefinitionParser} to register a {@link AuditingEventListener} to transparently set auditing information on
|
* {@link BeanDefinitionParser} to register a {@link AuditingEventListener} to transparently set auditing information on
|
||||||
* an entity.
|
* an entity.
|
||||||
*
|
*
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
*/
|
*/
|
||||||
public class MongoAuditingBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
|
public class MongoAuditingBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#getBeanClass(org.w3c.dom.Element)
|
* @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#getBeanClass(org.w3c.dom.Element)
|
||||||
*/
|
*/
|
||||||
@@ -47,7 +47,7 @@ public class MongoAuditingBeanDefinitionParser extends AbstractSingleBeanDefinit
|
|||||||
return AuditingEventListener.class;
|
return AuditingEventListener.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#shouldGenerateId()
|
* @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#shouldGenerateId()
|
||||||
*/
|
*/
|
||||||
@@ -56,7 +56,7 @@ public class MongoAuditingBeanDefinitionParser extends AbstractSingleBeanDefinit
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#doParse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext, org.springframework.beans.factory.support.BeanDefinitionBuilder)
|
* @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#doParse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext, org.springframework.beans.factory.support.BeanDefinitionBuilder)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -37,13 +37,13 @@ import org.springframework.util.Assert;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link ImportBeanDefinitionRegistrar} to enable {@link EnableMongoAuditing} annotation.
|
* {@link ImportBeanDefinitionRegistrar} to enable {@link EnableMongoAuditing} annotation.
|
||||||
*
|
*
|
||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
*/
|
*/
|
||||||
class MongoAuditingRegistrar extends AuditingBeanDefinitionRegistrarSupport {
|
class MongoAuditingRegistrar extends AuditingBeanDefinitionRegistrarSupport {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport#getAnnotation()
|
* @see org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport#getAnnotation()
|
||||||
*/
|
*/
|
||||||
@@ -52,7 +52,7 @@ class MongoAuditingRegistrar extends AuditingBeanDefinitionRegistrarSupport {
|
|||||||
return EnableMongoAuditing.class;
|
return EnableMongoAuditing.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport#getAuditingHandlerBeanName()
|
* @see org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport#getAuditingHandlerBeanName()
|
||||||
*/
|
*/
|
||||||
@@ -61,7 +61,7 @@ class MongoAuditingRegistrar extends AuditingBeanDefinitionRegistrarSupport {
|
|||||||
return "mongoAuditingHandler";
|
return "mongoAuditingHandler";
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport#registerBeanDefinitions(org.springframework.core.type.AnnotationMetadata, org.springframework.beans.factory.support.BeanDefinitionRegistry)
|
* @see org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport#registerBeanDefinitions(org.springframework.core.type.AnnotationMetadata, org.springframework.beans.factory.support.BeanDefinitionRegistry)
|
||||||
*/
|
*/
|
||||||
@@ -74,7 +74,7 @@ class MongoAuditingRegistrar extends AuditingBeanDefinitionRegistrarSupport {
|
|||||||
super.registerBeanDefinitions(annotationMetadata, registry);
|
super.registerBeanDefinitions(annotationMetadata, registry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport#getAuditHandlerBeanDefinitionBuilder(org.springframework.data.auditing.config.AuditingConfiguration)
|
* @see org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport#getAuditHandlerBeanDefinitionBuilder(org.springframework.data.auditing.config.AuditingConfiguration)
|
||||||
*/
|
*/
|
||||||
@@ -92,7 +92,7 @@ class MongoAuditingRegistrar extends AuditingBeanDefinitionRegistrarSupport {
|
|||||||
return configureDefaultAuditHandlerAttributes(configuration, builder);
|
return configureDefaultAuditHandlerAttributes(configuration, builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport#registerAuditListener(org.springframework.beans.factory.config.BeanDefinition, org.springframework.beans.factory.support.BeanDefinitionRegistry)
|
* @see org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport#registerAuditListener(org.springframework.beans.factory.config.BeanDefinition, org.springframework.beans.factory.support.BeanDefinitionRegistry)
|
||||||
*/
|
*/
|
||||||
@@ -125,14 +125,14 @@ class MongoAuditingRegistrar extends AuditingBeanDefinitionRegistrarSupport {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link MongoMappingContextLookup} for the given {@link MappingMongoConverter}.
|
* Creates a new {@link MongoMappingContextLookup} for the given {@link MappingMongoConverter}.
|
||||||
*
|
*
|
||||||
* @param converter must not be {@literal null}.
|
* @param converter must not be {@literal null}.
|
||||||
*/
|
*/
|
||||||
public MongoMappingContextLookup(MappingMongoConverter converter) {
|
public MongoMappingContextLookup(MappingMongoConverter converter) {
|
||||||
this.converter = converter;
|
this.converter = converter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.beans.factory.FactoryBean#getObject()
|
* @see org.springframework.beans.factory.FactoryBean#getObject()
|
||||||
*/
|
*/
|
||||||
@@ -141,7 +141,7 @@ class MongoAuditingRegistrar extends AuditingBeanDefinitionRegistrarSupport {
|
|||||||
return converter.getMappingContext();
|
return converter.getMappingContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
|
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
|
||||||
*/
|
*/
|
||||||
@@ -150,7 +150,7 @@ class MongoAuditingRegistrar extends AuditingBeanDefinitionRegistrarSupport {
|
|||||||
return MappingContext.class;
|
return MappingContext.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.beans.factory.FactoryBean#isSingleton()
|
* @see org.springframework.beans.factory.FactoryBean#isSingleton()
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -29,13 +29,13 @@ import org.w3c.dom.Element;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Parser for {@code mongo-client} definitions.
|
* Parser for {@code mongo-client} definitions.
|
||||||
*
|
*
|
||||||
* @author Christoph Strobl
|
* @author Christoph Strobl
|
||||||
* @since 1.7
|
* @since 1.7
|
||||||
*/
|
*/
|
||||||
public class MongoClientParser implements BeanDefinitionParser {
|
public class MongoClientParser implements BeanDefinitionParser {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.beans.factory.xml.BeanDefinitionParser#parse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)
|
* @see org.springframework.beans.factory.xml.BeanDefinitionParser#parse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,206 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* 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.Arrays;
|
|
||||||
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.core.convert.converter.Converter;
|
|
||||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
|
||||||
import org.springframework.data.annotation.Persistent;
|
|
||||||
import org.springframework.data.convert.CustomConversions;
|
|
||||||
import org.springframework.data.mapping.context.MappingContext;
|
|
||||||
import org.springframework.data.mapping.context.MappingContextIsNewStrategyFactory;
|
|
||||||
import org.springframework.data.mapping.context.PersistentEntities;
|
|
||||||
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.core.convert.MongoCustomConversions;
|
|
||||||
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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base class for Spring Data MongoDB to be extended for JavaConfiguration usage.
|
|
||||||
*
|
|
||||||
* @author Mark Paluch
|
|
||||||
* @since 2.0
|
|
||||||
*/
|
|
||||||
public abstract class MongoConfigurationSupport {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the name of the database to connect to.
|
|
||||||
*
|
|
||||||
* @return must not be {@literal null}.
|
|
||||||
*/
|
|
||||||
protected abstract String getDatabaseName();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 MongoConfigurationSupport} 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() {
|
|
||||||
|
|
||||||
Package mappingBasePackage = getClass().getPackage();
|
|
||||||
return Collections.singleton(mappingBasePackage == null ? null : mappingBasePackage.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a {@link MongoMappingContext} equipped with entity classes scanned from the mapping base package.
|
|
||||||
*
|
|
||||||
* @see #getMappingBasePackages()
|
|
||||||
* @return
|
|
||||||
* @throws ClassNotFoundException
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public MongoMappingContext mongoMappingContext() throws ClassNotFoundException {
|
|
||||||
|
|
||||||
MongoMappingContext mappingContext = new MongoMappingContext();
|
|
||||||
mappingContext.setInitialEntitySet(getInitialEntitySet());
|
|
||||||
mappingContext.setSimpleTypeHolder(customConversions().getSimpleTypeHolder());
|
|
||||||
mappingContext.setFieldNamingStrategy(fieldNamingStrategy());
|
|
||||||
mappingContext.setAutoIndexCreation(autoIndexCreation());
|
|
||||||
|
|
||||||
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(
|
|
||||||
new PersistentEntities(Arrays.<MappingContext<?, ?>> asList(new MappingContext[] { 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 MongoCustomConversions} instance by default.
|
|
||||||
*
|
|
||||||
* @return must not be {@literal null}.
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public CustomConversions customConversions() {
|
|
||||||
return new MongoCustomConversions(Collections.emptyList());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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(), MongoConfigurationSupport.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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configure whether to automatically create indices for domain types by deriving the
|
|
||||||
* {@link org.springframework.data.mongodb.core.index.IndexDefinition} from the entity or not.
|
|
||||||
*
|
|
||||||
* @return {@literal true} by default. <br />
|
|
||||||
* <strong>INFO</strong>: As of 3.x the default will be set to {@literal false}.
|
|
||||||
* @since 2.2
|
|
||||||
*/
|
|
||||||
protected boolean autoIndexCreation() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -16,9 +16,7 @@
|
|||||||
package org.springframework.data.mongodb.config;
|
package org.springframework.data.mongodb.config;
|
||||||
|
|
||||||
import java.beans.PropertyEditorSupport;
|
import java.beans.PropertyEditorSupport;
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.net.URLDecoder;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -26,7 +24,6 @@ import java.util.Properties;
|
|||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import org.springframework.lang.Nullable;
|
|
||||||
import org.springframework.util.ReflectionUtils;
|
import org.springframework.util.ReflectionUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
@@ -46,23 +43,23 @@ public class MongoCredentialPropertyEditor extends PropertyEditorSupport {
|
|||||||
private static final Pattern GROUP_PATTERN = Pattern.compile("(\\\\?')(.*?)\\1");
|
private static final Pattern GROUP_PATTERN = Pattern.compile("(\\\\?')(.*?)\\1");
|
||||||
|
|
||||||
private static final String AUTH_MECHANISM_KEY = "uri.authMechanism";
|
private static final String AUTH_MECHANISM_KEY = "uri.authMechanism";
|
||||||
private static final String USERNAME_PASSWORD_DELIMITER = ":";
|
private static final String USERNAME_PASSWORD_DELIMINATOR = ":";
|
||||||
private static final String DATABASE_DELIMITER = "@";
|
private static final String DATABASE_DELIMINATOR = "@";
|
||||||
private static final String OPTIONS_DELIMITER = "?";
|
private static final String OPTIONS_DELIMINATOR = "?";
|
||||||
private static final String OPTION_VALUE_DELIMITER = "&";
|
private static final String OPTION_VALUE_DELIMINATOR = "&";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see java.beans.PropertyEditorSupport#setAsText(java.lang.String)
|
* @see java.beans.PropertyEditorSupport#setAsText(java.lang.String)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setAsText(@Nullable String text) throws IllegalArgumentException {
|
public void setAsText(String text) throws IllegalArgumentException {
|
||||||
|
|
||||||
if (!StringUtils.hasText(text)) {
|
if (!StringUtils.hasText(text)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<MongoCredential> credentials = new ArrayList<>();
|
List<MongoCredential> credentials = new ArrayList<MongoCredential>();
|
||||||
|
|
||||||
for (String credentialString : extractCredentialsString(text)) {
|
for (String credentialString : extractCredentialsString(text)) {
|
||||||
|
|
||||||
@@ -80,23 +77,12 @@ public class MongoCredentialPropertyEditor extends PropertyEditorSupport {
|
|||||||
|
|
||||||
verifyUserNamePresent(userNameAndPassword);
|
verifyUserNamePresent(userNameAndPassword);
|
||||||
credentials.add(MongoCredential.createGSSAPICredential(userNameAndPassword[0]));
|
credentials.add(MongoCredential.createGSSAPICredential(userNameAndPassword[0]));
|
||||||
} else if ("MONGODB-CR".equals(authMechanism)) {
|
} else if (MongoCredential.MONGODB_CR_MECHANISM.equals(authMechanism)) {
|
||||||
|
|
||||||
verifyUsernameAndPasswordPresent(userNameAndPassword);
|
verifyUsernameAndPasswordPresent(userNameAndPassword);
|
||||||
verifyDatabasePresent(database);
|
verifyDatabasePresent(database);
|
||||||
|
credentials.add(MongoCredential.createMongoCRCredential(userNameAndPassword[0], database,
|
||||||
Method createCRCredentialMethod = ReflectionUtils.findMethod(MongoCredential.class,
|
userNameAndPassword[1].toCharArray()));
|
||||||
"createMongoCRCredential", String.class, String.class, char[].class);
|
|
||||||
|
|
||||||
if (createCRCredentialMethod == null) {
|
|
||||||
throw new IllegalArgumentException("MONGODB-CR is no longer supported.");
|
|
||||||
}
|
|
||||||
|
|
||||||
MongoCredential credential = MongoCredential.class
|
|
||||||
.cast(ReflectionUtils.invokeMethod(createCRCredentialMethod, null, userNameAndPassword[0], database,
|
|
||||||
userNameAndPassword[1].toCharArray()));
|
|
||||||
credentials.add(credential);
|
|
||||||
|
|
||||||
} else if (MongoCredential.MONGODB_X509_MECHANISM.equals(authMechanism)) {
|
} else if (MongoCredential.MONGODB_X509_MECHANISM.equals(authMechanism)) {
|
||||||
|
|
||||||
verifyUserNamePresent(userNameAndPassword);
|
verifyUserNamePresent(userNameAndPassword);
|
||||||
@@ -113,12 +99,20 @@ public class MongoCredentialPropertyEditor extends PropertyEditorSupport {
|
|||||||
verifyDatabasePresent(database);
|
verifyDatabasePresent(database);
|
||||||
credentials.add(MongoCredential.createScramSha1Credential(userNameAndPassword[0], database,
|
credentials.add(MongoCredential.createScramSha1Credential(userNameAndPassword[0], database,
|
||||||
userNameAndPassword[1].toCharArray()));
|
userNameAndPassword[1].toCharArray()));
|
||||||
} else if (MongoCredential.SCRAM_SHA_256_MECHANISM.equals(authMechanism)) {
|
} 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);
|
verifyUsernameAndPasswordPresent(userNameAndPassword);
|
||||||
verifyDatabasePresent(database);
|
verifyDatabasePresent(database);
|
||||||
credentials.add(MongoCredential.createScramSha256Credential(userNameAndPassword[0], database,
|
credentials.add(MongoCredential.class.cast(ReflectionUtils.invokeMethod(createScramSha256Credential, null,
|
||||||
userNameAndPassword[1].toCharArray()));
|
userNameAndPassword[0], database, userNameAndPassword[1].toCharArray())));
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
String.format("Cannot create MongoCredentials for unknown auth mechanism '%s'!", authMechanism));
|
String.format("Cannot create MongoCredentials for unknown auth mechanism '%s'!", authMechanism));
|
||||||
@@ -139,7 +133,7 @@ public class MongoCredentialPropertyEditor extends PropertyEditorSupport {
|
|||||||
private List<String> extractCredentialsString(String source) {
|
private List<String> extractCredentialsString(String source) {
|
||||||
|
|
||||||
Matcher matcher = GROUP_PATTERN.matcher(source);
|
Matcher matcher = GROUP_PATTERN.matcher(source);
|
||||||
List<String> list = new ArrayList<>();
|
List<String> list = new ArrayList<String>();
|
||||||
|
|
||||||
while (matcher.find()) {
|
while (matcher.find()) {
|
||||||
|
|
||||||
@@ -156,45 +150,39 @@ public class MongoCredentialPropertyEditor extends PropertyEditorSupport {
|
|||||||
|
|
||||||
private static String[] extractUserNameAndPassword(String text) {
|
private static String[] extractUserNameAndPassword(String text) {
|
||||||
|
|
||||||
int index = text.lastIndexOf(DATABASE_DELIMITER);
|
int index = text.lastIndexOf(DATABASE_DELIMINATOR);
|
||||||
|
|
||||||
index = index != -1 ? index : text.lastIndexOf(OPTIONS_DELIMITER);
|
index = index != -1 ? index : text.lastIndexOf(OPTIONS_DELIMINATOR);
|
||||||
|
|
||||||
if (index == -1) {
|
return index == -1 ? new String[] {} : text.substring(0, index).split(USERNAME_PASSWORD_DELIMINATOR);
|
||||||
return new String[] {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return Arrays.stream(text.substring(0, index).split(USERNAME_PASSWORD_DELIMITER))
|
|
||||||
.map(MongoCredentialPropertyEditor::decodeParameter).toArray(String[]::new);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String extractDB(String text) {
|
private static String extractDB(String text) {
|
||||||
|
|
||||||
int dbSeparationIndex = text.lastIndexOf(DATABASE_DELIMITER);
|
int dbSeperationIndex = text.lastIndexOf(DATABASE_DELIMINATOR);
|
||||||
|
|
||||||
if (dbSeparationIndex == -1) {
|
if (dbSeperationIndex == -1) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
String tmp = text.substring(dbSeparationIndex + 1);
|
String tmp = text.substring(dbSeperationIndex + 1);
|
||||||
int optionsSeparationIndex = tmp.lastIndexOf(OPTIONS_DELIMITER);
|
int optionsSeperationIndex = tmp.lastIndexOf(OPTIONS_DELIMINATOR);
|
||||||
|
|
||||||
return optionsSeparationIndex > -1 ? tmp.substring(0, optionsSeparationIndex) : tmp;
|
return optionsSeperationIndex > -1 ? tmp.substring(0, optionsSeperationIndex) : tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Properties extractOptions(String text) {
|
private static Properties extractOptions(String text) {
|
||||||
|
|
||||||
int optionsSeparationIndex = text.lastIndexOf(OPTIONS_DELIMITER);
|
int optionsSeperationIndex = text.lastIndexOf(OPTIONS_DELIMINATOR);
|
||||||
int dbSeparationIndex = text.lastIndexOf(DATABASE_DELIMITER);
|
int dbSeperationIndex = text.lastIndexOf(DATABASE_DELIMINATOR);
|
||||||
|
|
||||||
if (optionsSeparationIndex == -1 || dbSeparationIndex > optionsSeparationIndex) {
|
if (optionsSeperationIndex == -1 || dbSeperationIndex > optionsSeperationIndex) {
|
||||||
return new Properties();
|
return new Properties();
|
||||||
}
|
}
|
||||||
|
|
||||||
Properties properties = new Properties();
|
Properties properties = new Properties();
|
||||||
|
|
||||||
for (String option : text.substring(optionsSeparationIndex + 1).split(OPTION_VALUE_DELIMITER)) {
|
for (String option : text.substring(optionsSeperationIndex + 1).split(OPTION_VALUE_DELIMINATOR)) {
|
||||||
|
|
||||||
String[] optionArgs = option.split("=");
|
String[] optionArgs = option.split("=");
|
||||||
|
|
||||||
if (optionArgs.length == 1) {
|
if (optionArgs.length == 1) {
|
||||||
@@ -230,12 +218,4 @@ public class MongoCredentialPropertyEditor extends PropertyEditorSupport {
|
|||||||
throw new IllegalArgumentException("Credentials need to specify username!");
|
throw new IllegalArgumentException("Credentials need to specify username!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String decodeParameter(String it) {
|
|
||||||
try {
|
|
||||||
return URLDecoder.decode(it, "UTF-8");
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
throw new IllegalArgumentException("o_O UTF-8 not supported!", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2019 the original author or authors.
|
* Copyright 2011-2015 by the original author(s).
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -30,10 +30,10 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
|||||||
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
|
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
|
||||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||||
import org.springframework.beans.factory.xml.ParserContext;
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
|
import org.springframework.data.authentication.UserCredentials;
|
||||||
import org.springframework.data.config.BeanComponentDefinitionBuilder;
|
import org.springframework.data.config.BeanComponentDefinitionBuilder;
|
||||||
import org.springframework.data.mongodb.core.MongoClientFactoryBean;
|
import org.springframework.data.mongodb.core.MongoFactoryBean;
|
||||||
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
|
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
|
||||||
import org.springframework.lang.Nullable;
|
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
@@ -43,13 +43,12 @@ import com.mongodb.MongoURI;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link BeanDefinitionParser} to parse {@code db-factory} elements into {@link BeanDefinition}s.
|
* {@link BeanDefinitionParser} to parse {@code db-factory} elements into {@link BeanDefinition}s.
|
||||||
*
|
*
|
||||||
* @author Jon Brisbin
|
* @author Jon Brisbin
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
* @author Christoph Strobl
|
* @author Christoph Strobl
|
||||||
* @author Viktor Khoroshko
|
* @author Viktor Khoroshko
|
||||||
* @author Mark Paluch
|
|
||||||
*/
|
*/
|
||||||
public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
||||||
|
|
||||||
@@ -64,7 +63,7 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
|||||||
MONGO_URI_ALLOWED_ADDITIONAL_ATTRIBUTES = Collections.unmodifiableSet(mongoUriAllowedAdditionalAttributes);
|
MONGO_URI_ALLOWED_ADDITIONAL_ATTRIBUTES = Collections.unmodifiableSet(mongoUriAllowedAdditionalAttributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#resolveId(org.w3c.dom.Element, org.springframework.beans.factory.support.AbstractBeanDefinition, org.springframework.beans.factory.xml.ParserContext)
|
* @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#resolveId(org.w3c.dom.Element, org.springframework.beans.factory.support.AbstractBeanDefinition, org.springframework.beans.factory.xml.ParserContext)
|
||||||
*/
|
*/
|
||||||
@@ -76,7 +75,7 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
|||||||
return StringUtils.hasText(id) ? id : BeanNames.DB_FACTORY_BEAN_NAME;
|
return StringUtils.hasText(id) ? id : BeanNames.DB_FACTORY_BEAN_NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#parseInternal(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)
|
* @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#parseInternal(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)
|
||||||
*/
|
*/
|
||||||
@@ -100,6 +99,8 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
|||||||
String mongoRef = element.getAttribute("mongo-ref");
|
String mongoRef = element.getAttribute("mongo-ref");
|
||||||
String dbname = element.getAttribute("dbname");
|
String dbname = element.getAttribute("dbname");
|
||||||
|
|
||||||
|
BeanDefinition userCredentials = getUserCredentialsBeanDefinition(element, parserContext);
|
||||||
|
|
||||||
// Defaulting
|
// Defaulting
|
||||||
if (StringUtils.hasText(mongoRef)) {
|
if (StringUtils.hasText(mongoRef)) {
|
||||||
dbFactoryBuilder.addConstructorArgReference(mongoRef);
|
dbFactoryBuilder.addConstructorArgReference(mongoRef);
|
||||||
@@ -108,6 +109,8 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dbFactoryBuilder.addConstructorArgValue(StringUtils.hasText(dbname) ? dbname : "db");
|
dbFactoryBuilder.addConstructorArgValue(StringUtils.hasText(dbname) ? dbname : "db");
|
||||||
|
dbFactoryBuilder.addConstructorArgValue(userCredentials);
|
||||||
|
dbFactoryBuilder.addConstructorArgValue(element.getAttribute("authentication-dbname"));
|
||||||
|
|
||||||
BeanDefinitionBuilder writeConcernPropertyEditorBuilder = getWriteConcernPropertyEditorBuilder();
|
BeanDefinitionBuilder writeConcernPropertyEditorBuilder = getWriteConcernPropertyEditorBuilder();
|
||||||
|
|
||||||
@@ -121,31 +124,52 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
|||||||
/**
|
/**
|
||||||
* Registers a default {@link BeanDefinition} of a {@link Mongo} instance and returns the name under which the
|
* Registers a default {@link BeanDefinition} of a {@link Mongo} instance and returns the name under which the
|
||||||
* {@link Mongo} instance was registered under.
|
* {@link Mongo} instance was registered under.
|
||||||
*
|
*
|
||||||
* @param element must not be {@literal null}.
|
* @param element must not be {@literal null}.
|
||||||
* @param parserContext must not be {@literal null}.
|
* @param parserContext must not be {@literal null}.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private BeanDefinition registerMongoBeanDefinition(Element element, ParserContext parserContext) {
|
private BeanDefinition registerMongoBeanDefinition(Element element, ParserContext parserContext) {
|
||||||
|
|
||||||
BeanDefinitionBuilder mongoBuilder = BeanDefinitionBuilder.genericBeanDefinition(MongoClientFactoryBean.class);
|
BeanDefinitionBuilder mongoBuilder = BeanDefinitionBuilder.genericBeanDefinition(MongoFactoryBean.class);
|
||||||
setPropertyValue(mongoBuilder, element, "host");
|
setPropertyValue(mongoBuilder, element, "host");
|
||||||
setPropertyValue(mongoBuilder, element, "port");
|
setPropertyValue(mongoBuilder, element, "port");
|
||||||
|
|
||||||
return getSourceBeanDefinition(mongoBuilder, parserContext, element);
|
return getSourceBeanDefinition(mongoBuilder, parserContext, element);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@link BeanDefinition} for a {@link UserCredentials} object.
|
||||||
|
*
|
||||||
|
* @param element
|
||||||
|
* @return the {@link BeanDefinition} or {@literal null} if neither username nor password given.
|
||||||
|
*/
|
||||||
|
private BeanDefinition getUserCredentialsBeanDefinition(Element element, ParserContext context) {
|
||||||
|
|
||||||
|
String username = element.getAttribute("username");
|
||||||
|
String password = element.getAttribute("password");
|
||||||
|
|
||||||
|
if (!StringUtils.hasText(username) && !StringUtils.hasText(password)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
BeanDefinitionBuilder userCredentialsBuilder = BeanDefinitionBuilder.genericBeanDefinition(UserCredentials.class);
|
||||||
|
userCredentialsBuilder.addConstructorArgValue(StringUtils.hasText(username) ? username : null);
|
||||||
|
userCredentialsBuilder.addConstructorArgValue(StringUtils.hasText(password) ? password : null);
|
||||||
|
|
||||||
|
return getSourceBeanDefinition(userCredentialsBuilder, context, element);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@link BeanDefinition} for a {@link MongoURI} or {@link MongoClientURI} depending on configured
|
* Creates a {@link BeanDefinition} for a {@link MongoURI} or {@link MongoClientURI} depending on configured
|
||||||
* attributes. <br />
|
* attributes. <br />
|
||||||
* Errors when configured element contains {@literal uri} or {@literal client-uri} along with other attributes except
|
* Errors when configured element contains {@literal uri} or {@literal client-uri} along with other attributes except
|
||||||
* {@literal write-concern} and/or {@literal id}.
|
* {@literal write-concern} and/or {@literal id}.
|
||||||
*
|
*
|
||||||
* @param element must not be {@literal null}.
|
* @param element must not be {@literal null}.
|
||||||
* @param parserContext
|
* @param parserContext
|
||||||
* @return {@literal null} in case no client-/uri defined.
|
* @return {@literal null} in case no client-/uri defined.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
|
||||||
private BeanDefinition getMongoUri(Element element, ParserContext parserContext) {
|
private BeanDefinition getMongoUri(Element element, ParserContext parserContext) {
|
||||||
|
|
||||||
boolean hasClientUri = element.hasAttribute("client-uri");
|
boolean hasClientUri = element.hasAttribute("client-uri");
|
||||||
@@ -169,7 +193,7 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
|||||||
parserContext.extractSource(element));
|
parserContext.extractSource(element));
|
||||||
}
|
}
|
||||||
|
|
||||||
Class<?> type = MongoClientURI.class;
|
Class<?> type = hasClientUri ? MongoClientURI.class : MongoURI.class;
|
||||||
String uri = hasClientUri ? element.getAttribute("client-uri") : element.getAttribute("uri");
|
String uri = hasClientUri ? element.getAttribute("client-uri") : element.getAttribute("uri");
|
||||||
|
|
||||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(type);
|
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(type);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -26,19 +26,12 @@ import org.springframework.data.mongodb.monitor.*;
|
|||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Mark Pollack
|
|
||||||
* @author Thomas Risberg
|
|
||||||
* @author John Brisbin
|
|
||||||
* @author Oliver Gierke
|
|
||||||
* @author Christoph Strobl
|
|
||||||
*/
|
|
||||||
public class MongoJmxParser implements BeanDefinitionParser {
|
public class MongoJmxParser implements BeanDefinitionParser {
|
||||||
|
|
||||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||||
String name = element.getAttribute("mongo-ref");
|
String name = element.getAttribute("mongo-ref");
|
||||||
if (!StringUtils.hasText(name)) {
|
if (!StringUtils.hasText(name)) {
|
||||||
name = BeanNames.MONGO_BEAN_NAME;
|
name = "mongo";
|
||||||
}
|
}
|
||||||
registerJmxComponents(name, element, parserContext);
|
registerJmxComponents(name, element, parserContext);
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -19,7 +19,7 @@ import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link org.springframework.beans.factory.xml.NamespaceHandler} for Mongo DB configuration.
|
* {@link org.springframework.beans.factory.xml.NamespaceHandler} for Mongo DB configuration.
|
||||||
*
|
*
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Martin Baumgartner
|
* @author Martin Baumgartner
|
||||||
* @author Christoph Strobl
|
* @author Christoph Strobl
|
||||||
@@ -33,6 +33,7 @@ public class MongoNamespaceHandler extends NamespaceHandlerSupport {
|
|||||||
public void init() {
|
public void init() {
|
||||||
|
|
||||||
registerBeanDefinitionParser("mapping-converter", new MappingMongoConverterParser());
|
registerBeanDefinitionParser("mapping-converter", new MappingMongoConverterParser());
|
||||||
|
registerBeanDefinitionParser("mongo", new MongoParser());
|
||||||
registerBeanDefinitionParser("mongo-client", new MongoClientParser());
|
registerBeanDefinitionParser("mongo-client", new MongoClientParser());
|
||||||
registerBeanDefinitionParser("db-factory", new MongoDbFactoryParser());
|
registerBeanDefinitionParser("db-factory", new MongoDbFactoryParser());
|
||||||
registerBeanDefinitionParser("jmx", new MongoJmxParser());
|
registerBeanDefinitionParser("jmx", new MongoJmxParser());
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* 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.config.BeanComponentDefinitionBuilder;
|
||||||
|
import org.springframework.data.config.ParsingUtils;
|
||||||
|
import org.springframework.data.mongodb.core.MongoFactoryBean;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parser for <mongo;gt; definitions.
|
||||||
|
*
|
||||||
|
* @author Mark Pollack
|
||||||
|
* @author Oliver Gierke
|
||||||
|
* @author Christoph Strobl
|
||||||
|
*/
|
||||||
|
public class MongoParser implements BeanDefinitionParser {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.beans.factory.xml.BeanDefinitionParser#parse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)
|
||||||
|
*/
|
||||||
|
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||||
|
|
||||||
|
Object source = parserContext.extractSource(element);
|
||||||
|
String id = element.getAttribute("id");
|
||||||
|
|
||||||
|
BeanComponentDefinitionBuilder helper = new BeanComponentDefinitionBuilder(element, parserContext);
|
||||||
|
|
||||||
|
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MongoFactoryBean.class);
|
||||||
|
ParsingUtils.setPropertyValue(builder, element, "port", "port");
|
||||||
|
ParsingUtils.setPropertyValue(builder, element, "host", "host");
|
||||||
|
ParsingUtils.setPropertyValue(builder, element, "write-concern", "writeConcern");
|
||||||
|
|
||||||
|
MongoParsingUtils.parseMongoOptions(element, builder);
|
||||||
|
MongoParsingUtils.parseReplicaSet(element, builder);
|
||||||
|
|
||||||
|
String defaultedId = StringUtils.hasText(id) ? id : BeanNames.MONGO_BEAN_NAME;
|
||||||
|
|
||||||
|
parserContext.pushContainingComponent(new CompositeComponentDefinition("Mongo", source));
|
||||||
|
|
||||||
|
BeanComponentDefinition mongoComponent = helper.getComponent(builder, defaultedId);
|
||||||
|
parserContext.registerBeanComponent(mongoComponent);
|
||||||
|
BeanComponentDefinition serverAddressPropertyEditor = helper.getComponent(MongoParsingUtils
|
||||||
|
.getServerAddressPropertyEditorBuilder());
|
||||||
|
parserContext.registerBeanComponent(serverAddressPropertyEditor);
|
||||||
|
BeanComponentDefinition writeConcernPropertyEditor = helper.getComponent(MongoParsingUtils
|
||||||
|
.getWriteConcernPropertyEditorBuilder());
|
||||||
|
parserContext.registerBeanComponent(writeConcernPropertyEditor);
|
||||||
|
|
||||||
|
parserContext.popAndRegisterContainingComponent();
|
||||||
|
|
||||||
|
return mongoComponent.getBeanDefinition();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -25,12 +25,13 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
|||||||
import org.springframework.beans.factory.support.ManagedMap;
|
import org.springframework.beans.factory.support.ManagedMap;
|
||||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||||
import org.springframework.data.mongodb.core.MongoClientOptionsFactoryBean;
|
import org.springframework.data.mongodb.core.MongoClientOptionsFactoryBean;
|
||||||
|
import org.springframework.data.mongodb.core.MongoOptionsFactoryBean;
|
||||||
import org.springframework.util.xml.DomUtils;
|
import org.springframework.util.xml.DomUtils;
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility methods for {@link BeanDefinitionParser} implementations for MongoDB.
|
* Utility methods for {@link BeanDefinitionParser} implementations for MongoDB.
|
||||||
*
|
*
|
||||||
* @author Mark Pollack
|
* @author Mark Pollack
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
@@ -43,7 +44,7 @@ abstract class MongoParsingUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the mongo replica-set element.
|
* Parses the mongo replica-set element.
|
||||||
*
|
*
|
||||||
* @param parserContext the parser context
|
* @param parserContext the parser context
|
||||||
* @param element the mongo element
|
* @param element the mongo element
|
||||||
* @param mongoBuilder the bean definition builder to populate
|
* @param mongoBuilder the bean definition builder to populate
|
||||||
@@ -53,10 +54,46 @@ abstract class MongoParsingUtils {
|
|||||||
setPropertyValue(mongoBuilder, element, "replica-set", "replicaSetSeeds");
|
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
|
* Parses the {@code mongo:client-options} sub-element. Populates the given attribute factory with the proper
|
||||||
* attributes.
|
* attributes.
|
||||||
*
|
*
|
||||||
* @param element must not be {@literal null}.
|
* @param element must not be {@literal null}.
|
||||||
* @param mongoClientBuilder must not be {@literal null}.
|
* @param mongoClientBuilder must not be {@literal null}.
|
||||||
* @return
|
* @return
|
||||||
@@ -102,7 +139,7 @@ abstract class MongoParsingUtils {
|
|||||||
/**
|
/**
|
||||||
* Returns the {@link BeanDefinitionBuilder} to build a {@link BeanDefinition} for a
|
* Returns the {@link BeanDefinitionBuilder} to build a {@link BeanDefinition} for a
|
||||||
* {@link WriteConcernPropertyEditor}.
|
* {@link WriteConcernPropertyEditor}.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
static BeanDefinitionBuilder getWriteConcernPropertyEditorBuilder() {
|
static BeanDefinitionBuilder getWriteConcernPropertyEditorBuilder() {
|
||||||
@@ -135,7 +172,7 @@ abstract class MongoParsingUtils {
|
|||||||
/**
|
/**
|
||||||
* Returns the {@link BeanDefinitionBuilder} to build a {@link BeanDefinition} for a
|
* Returns the {@link BeanDefinitionBuilder} to build a {@link BeanDefinition} for a
|
||||||
* {@link ReadPreferencePropertyEditor}.
|
* {@link ReadPreferencePropertyEditor}.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* @since 1.7
|
* @since 1.7
|
||||||
*/
|
*/
|
||||||
@@ -153,7 +190,7 @@ abstract class MongoParsingUtils {
|
|||||||
/**
|
/**
|
||||||
* Returns the {@link BeanDefinitionBuilder} to build a {@link BeanDefinition} for a
|
* Returns the {@link BeanDefinitionBuilder} to build a {@link BeanDefinition} for a
|
||||||
* {@link MongoCredentialPropertyEditor}.
|
* {@link MongoCredentialPropertyEditor}.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* @since 1.7
|
* @since 1.7
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -33,13 +33,13 @@ import org.w3c.dom.Element;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link BeanDefinitionParser} to parse {@code template} elements into {@link BeanDefinition}s.
|
* {@link BeanDefinitionParser} to parse {@code template} elements into {@link BeanDefinition}s.
|
||||||
*
|
*
|
||||||
* @author Martin Baumgartner
|
* @author Martin Baumgartner
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
*/
|
*/
|
||||||
class MongoTemplateParser extends AbstractBeanDefinitionParser {
|
class MongoTemplateParser extends AbstractBeanDefinitionParser {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#resolveId(org.w3c.dom.Element, org.springframework.beans.factory.support.AbstractBeanDefinition, org.springframework.beans.factory.xml.ParserContext)
|
* @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#resolveId(org.w3c.dom.Element, org.springframework.beans.factory.support.AbstractBeanDefinition, org.springframework.beans.factory.xml.ParserContext)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -17,13 +17,11 @@ package org.springframework.data.mongodb.config;
|
|||||||
|
|
||||||
import java.beans.PropertyEditorSupport;
|
import java.beans.PropertyEditorSupport;
|
||||||
|
|
||||||
import org.springframework.lang.Nullable;
|
|
||||||
|
|
||||||
import com.mongodb.ReadPreference;
|
import com.mongodb.ReadPreference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a {@link String} to a {@link ReadPreference}.
|
* Parse a {@link String} to a {@link ReadPreference}.
|
||||||
*
|
*
|
||||||
* @author Christoph Strobl
|
* @author Christoph Strobl
|
||||||
* @since 1.7
|
* @since 1.7
|
||||||
*/
|
*/
|
||||||
@@ -34,7 +32,7 @@ public class ReadPreferencePropertyEditor extends PropertyEditorSupport {
|
|||||||
* @see java.beans.PropertyEditorSupport#setAsText(java.lang.String)
|
* @see java.beans.PropertyEditorSupport#setAsText(java.lang.String)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setAsText(@Nullable String readPreferenceString) throws IllegalArgumentException {
|
public void setAsText(String readPreferenceString) throws IllegalArgumentException {
|
||||||
|
|
||||||
if (readPreferenceString == null) {
|
if (readPreferenceString == null) {
|
||||||
return;
|
return;
|
||||||
@@ -61,8 +59,8 @@ public class ReadPreferencePropertyEditor extends PropertyEditorSupport {
|
|||||||
} else if ("NEAREST".equalsIgnoreCase(readPreferenceString)) {
|
} else if ("NEAREST".equalsIgnoreCase(readPreferenceString)) {
|
||||||
setValue(ReadPreference.nearest());
|
setValue(ReadPreference.nearest());
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(String.format("Cannot find matching ReadPreference for %s",
|
||||||
String.format("Cannot find matching ReadPreference for %s", readPreferenceString));
|
readPreferenceString));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -23,7 +23,6 @@ import java.util.Set;
|
|||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.lang.Nullable;
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
@@ -31,11 +30,10 @@ import com.mongodb.ServerAddress;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a {@link String} to a {@link ServerAddress} array. The format is host1:port1,host2:port2,host3:port3.
|
* Parse a {@link String} to a {@link ServerAddress} array. The format is host1:port1,host2:port2,host3:port3.
|
||||||
*
|
*
|
||||||
* @author Mark Pollack
|
* @author Mark Pollack
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
* @author Christoph Strobl
|
|
||||||
*/
|
*/
|
||||||
public class ServerAddressPropertyEditor extends PropertyEditorSupport {
|
public class ServerAddressPropertyEditor extends PropertyEditorSupport {
|
||||||
|
|
||||||
@@ -51,7 +49,7 @@ public class ServerAddressPropertyEditor extends PropertyEditorSupport {
|
|||||||
* @see java.beans.PropertyEditorSupport#setAsText(java.lang.String)
|
* @see java.beans.PropertyEditorSupport#setAsText(java.lang.String)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setAsText(@Nullable String replicaSetString) {
|
public void setAsText(String replicaSetString) {
|
||||||
|
|
||||||
if (!StringUtils.hasText(replicaSetString)) {
|
if (!StringUtils.hasText(replicaSetString)) {
|
||||||
setValue(null);
|
setValue(null);
|
||||||
@@ -80,11 +78,10 @@ public class ServerAddressPropertyEditor extends PropertyEditorSupport {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the given source into a {@link ServerAddress}.
|
* Parses the given source into a {@link ServerAddress}.
|
||||||
*
|
*
|
||||||
* @param source
|
* @param source
|
||||||
* @return the
|
* @return the
|
||||||
*/
|
*/
|
||||||
@Nullable
|
|
||||||
private ServerAddress parseServerAddress(String source) {
|
private ServerAddress parseServerAddress(String source) {
|
||||||
|
|
||||||
if (!StringUtils.hasText(source)) {
|
if (!StringUtils.hasText(source)) {
|
||||||
@@ -115,7 +112,7 @@ public class ServerAddressPropertyEditor extends PropertyEditorSupport {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract the host and port from the given {@link String}.
|
* Extract the host and port from the given {@link String}.
|
||||||
*
|
*
|
||||||
* @param addressAndPortSource must not be {@literal null}.
|
* @param addressAndPortSource must not be {@literal null}.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -21,12 +21,12 @@ import com.mongodb.WriteConcern;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Converter to create {@link WriteConcern} instances from String representations.
|
* Converter to create {@link WriteConcern} instances from String representations.
|
||||||
*
|
*
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
*/
|
*/
|
||||||
public class StringToWriteConcernConverter implements Converter<String, WriteConcern> {
|
public class StringToWriteConcernConverter implements Converter<String, WriteConcern> {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -17,9 +17,6 @@ package org.springframework.data.mongodb.config;
|
|||||||
|
|
||||||
import java.beans.PropertyEditorSupport;
|
import java.beans.PropertyEditorSupport;
|
||||||
|
|
||||||
import org.springframework.lang.Nullable;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import com.mongodb.WriteConcern;
|
import com.mongodb.WriteConcern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -27,9 +24,8 @@ import com.mongodb.WriteConcern;
|
|||||||
* {@link WriteConcern#valueOf(String)}, use the well known {@link WriteConcern} value, otherwise pass the string as is
|
* {@link WriteConcern#valueOf(String)}, use the well known {@link WriteConcern} value, otherwise pass the string as is
|
||||||
* to the constructor of the write concern. There is no support for other constructor signatures when parsing from a
|
* to the constructor of the write concern. There is no support for other constructor signatures when parsing from a
|
||||||
* string value.
|
* string value.
|
||||||
*
|
*
|
||||||
* @author Mark Pollack
|
* @author Mark Pollack
|
||||||
* @author Christoph Strobl
|
|
||||||
*/
|
*/
|
||||||
public class WriteConcernPropertyEditor extends PropertyEditorSupport {
|
public class WriteConcernPropertyEditor extends PropertyEditorSupport {
|
||||||
|
|
||||||
@@ -37,11 +33,7 @@ public class WriteConcernPropertyEditor extends PropertyEditorSupport {
|
|||||||
* Parse a string to a List<ServerAddress>
|
* Parse a string to a List<ServerAddress>
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setAsText(@Nullable String writeConcernString) {
|
public void setAsText(String writeConcernString) {
|
||||||
|
|
||||||
if (!StringUtils.hasText(writeConcernString)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
WriteConcern writeConcern = WriteConcern.valueOf(writeConcernString);
|
WriteConcern writeConcern = WriteConcern.valueOf(writeConcernString);
|
||||||
if (writeConcern != null) {
|
if (writeConcern != null) {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Spring XML namespace configuration for MongoDB specific repositories.
|
* Spring XML namespace configuration for MongoDB specific repositories.
|
||||||
*/
|
*/
|
||||||
@org.springframework.lang.NonNullApi
|
|
||||||
package org.springframework.data.mongodb.config;
|
package org.springframework.data.mongodb.config;
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -17,37 +17,28 @@ package org.springframework.data.mongodb.core;
|
|||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import org.bson.Document;
|
|
||||||
import org.springframework.data.mapping.context.MappingContext;
|
import org.springframework.data.mapping.context.MappingContext;
|
||||||
import org.springframework.data.mongodb.core.aggregation.Aggregation;
|
import org.springframework.data.mongodb.core.aggregation.Aggregation;
|
||||||
import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
|
|
||||||
import org.springframework.data.mongodb.core.aggregation.AggregationOperationContext;
|
import org.springframework.data.mongodb.core.aggregation.AggregationOperationContext;
|
||||||
import org.springframework.data.mongodb.core.aggregation.AggregationOptions;
|
|
||||||
import org.springframework.data.mongodb.core.aggregation.CountOperation;
|
|
||||||
import org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext;
|
import org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext;
|
||||||
import org.springframework.data.mongodb.core.aggregation.TypedAggregation;
|
import org.springframework.data.mongodb.core.aggregation.TypedAggregation;
|
||||||
import org.springframework.data.mongodb.core.convert.QueryMapper;
|
import org.springframework.data.mongodb.core.convert.QueryMapper;
|
||||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||||
import org.springframework.data.mongodb.core.query.CriteriaDefinition;
|
|
||||||
import org.springframework.data.mongodb.core.query.Query;
|
|
||||||
import org.springframework.lang.Nullable;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.util.ObjectUtils;
|
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
|
* Utility methods to map {@link org.springframework.data.mongodb.core.aggregation.Aggregation} pipeline definitions and
|
||||||
* create type-bound {@link AggregationOperationContext}.
|
* create type-bound {@link AggregationOperationContext}.
|
||||||
*
|
*
|
||||||
* @author Christoph Strobl
|
* @author Christoph Strobl
|
||||||
* @author Mark Paluch
|
* @author Mark Paluch
|
||||||
* @since 2.1
|
* @since 1.10.13
|
||||||
*/
|
*/
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
class AggregationUtil {
|
class AggregationUtil {
|
||||||
@@ -64,8 +55,7 @@ class AggregationUtil {
|
|||||||
* @param context can be {@literal null}.
|
* @param context can be {@literal null}.
|
||||||
* @return the root {@link AggregationOperationContext} to use.
|
* @return the root {@link AggregationOperationContext} to use.
|
||||||
*/
|
*/
|
||||||
AggregationOperationContext prepareAggregationContext(Aggregation aggregation,
|
AggregationOperationContext prepareAggregationContext(Aggregation aggregation, AggregationOperationContext context) {
|
||||||
@Nullable AggregationOperationContext context) {
|
|
||||||
|
|
||||||
if (context != null) {
|
if (context != null) {
|
||||||
return context;
|
return context;
|
||||||
@@ -86,13 +76,16 @@ class AggregationUtil {
|
|||||||
* @param context
|
* @param context
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
List<Document> createPipeline(Aggregation aggregation, AggregationOperationContext context) {
|
DBObject createPipeline(String collectionName, Aggregation aggregation, AggregationOperationContext context) {
|
||||||
|
|
||||||
if (!ObjectUtils.nullSafeEquals(context, Aggregation.DEFAULT_CONTEXT)) {
|
if (!ObjectUtils.nullSafeEquals(context, Aggregation.DEFAULT_CONTEXT)) {
|
||||||
return aggregation.toPipeline(context);
|
return aggregation.toDbObject(collectionName, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mapAggregationPipeline(aggregation.toPipeline(context));
|
DBObject command = aggregation.toDbObject(collectionName, context);
|
||||||
|
command.put("pipeline", mapAggregationPipeline((List) command.get("pipeline")));
|
||||||
|
|
||||||
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -102,69 +95,27 @@ class AggregationUtil {
|
|||||||
* @param context
|
* @param context
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
Document createCommand(String collection, Aggregation aggregation, AggregationOperationContext context) {
|
DBObject createCommand(String collection, Aggregation aggregation, AggregationOperationContext context) {
|
||||||
|
|
||||||
Document command = aggregation.toDocument(collection, context);
|
DBObject command = aggregation.toDbObject(collection, context);
|
||||||
|
|
||||||
if (!ObjectUtils.nullSafeEquals(context, Aggregation.DEFAULT_CONTEXT)) {
|
if (!ObjectUtils.nullSafeEquals(context, Aggregation.DEFAULT_CONTEXT)) {
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
command.put("pipeline", mapAggregationPipeline(command.get("pipeline", List.class)));
|
command.put("pipeline", mapAggregationPipeline((List) command.get("pipeline")));
|
||||||
|
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private BasicDBList mapAggregationPipeline(List<DBObject> pipeline) {
|
||||||
* Create a {@code $count} aggregation for {@link Query} and optionally a {@link Class entity class}.
|
|
||||||
*
|
|
||||||
* @param query must not be {@literal null}.
|
|
||||||
* @param entityClass can be {@literal null} if the {@link Query} object is empty.
|
|
||||||
* @return the {@link Aggregation} pipeline definition to run a {@code $count} aggregation.
|
|
||||||
*/
|
|
||||||
Aggregation createCountAggregation(Query query, @Nullable Class<?> entityClass) {
|
|
||||||
|
|
||||||
List<AggregationOperation> pipeline = computeCountAggregationPipeline(query, entityClass);
|
BasicDBList mapped = new BasicDBList();
|
||||||
|
|
||||||
Aggregation aggregation = entityClass != null ? Aggregation.newAggregation(entityClass, pipeline)
|
for (DBObject stage : pipeline) {
|
||||||
: Aggregation.newAggregation(pipeline);
|
mapped.add(queryMapper.getMappedObject(stage, null));
|
||||||
aggregation.withOptions(AggregationOptions.builder().collation(query.getCollation().orElse(null)).build());
|
|
||||||
|
|
||||||
return aggregation;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<AggregationOperation> computeCountAggregationPipeline(Query query, @Nullable Class<?> entityType) {
|
|
||||||
|
|
||||||
CountOperation count = Aggregation.count().as("totalEntityCount");
|
|
||||||
if (query.getQueryObject().isEmpty()) {
|
|
||||||
return Collections.singletonList(count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert.notNull(entityType, "Entity type must not be null!");
|
return mapped;
|
||||||
|
|
||||||
Document mappedQuery = queryMapper.getMappedObject(query.getQueryObject(),
|
|
||||||
mappingContext.getPersistentEntity(entityType));
|
|
||||||
|
|
||||||
CriteriaDefinition criteria = new CriteriaDefinition() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Document getCriteriaObject() {
|
|
||||||
return mappedQuery;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public String getKey() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return Arrays.asList(Aggregation.match(criteria), count);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Document> mapAggregationPipeline(List<Document> pipeline) {
|
|
||||||
|
|
||||||
return pipeline.stream().map(val -> queryMapper.getMappedObject(val, Optional.empty()))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -21,7 +21,7 @@ import org.springframework.data.mongodb.core.query.Query;
|
|||||||
import org.springframework.data.mongodb.core.query.Update;
|
import org.springframework.data.mongodb.core.query.Update;
|
||||||
import org.springframework.data.util.Pair;
|
import org.springframework.data.util.Pair;
|
||||||
|
|
||||||
import com.mongodb.bulk.BulkWriteResult;
|
import com.mongodb.BulkWriteResult;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bulk operations for insert/update/remove actions on a collection. These bulks operation are available since MongoDB
|
* Bulk operations for insert/update/remove actions on a collection. These bulks operation are available since MongoDB
|
||||||
@@ -38,7 +38,7 @@ public interface BulkOperations {
|
|||||||
/**
|
/**
|
||||||
* Mode for bulk operation.
|
* Mode for bulk operation.
|
||||||
**/
|
**/
|
||||||
enum BulkMode {
|
public enum BulkMode {
|
||||||
|
|
||||||
/** Perform bulk operations in sequence. The first error will cancel processing. */
|
/** Perform bulk operations in sequence. The first error will cancel processing. */
|
||||||
ORDERED,
|
ORDERED,
|
||||||
|
|||||||
@@ -1,202 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* 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 lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
|
|
||||||
|
|
||||||
import org.bson.BsonTimestamp;
|
|
||||||
import org.bson.BsonValue;
|
|
||||||
import org.bson.Document;
|
|
||||||
import org.springframework.data.mongodb.core.convert.MongoConverter;
|
|
||||||
import org.springframework.data.mongodb.core.messaging.Message;
|
|
||||||
import org.springframework.lang.Nullable;
|
|
||||||
import org.springframework.util.ClassUtils;
|
|
||||||
|
|
||||||
import com.mongodb.client.model.changestream.ChangeStreamDocument;
|
|
||||||
import com.mongodb.client.model.changestream.OperationType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link Message} implementation specific to MongoDB <a href="https://docs.mongodb.com/manual/changeStreams/">Change
|
|
||||||
* Streams</a>.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @author Mark Paluch
|
|
||||||
* @since 2.1
|
|
||||||
*/
|
|
||||||
@EqualsAndHashCode
|
|
||||||
public class ChangeStreamEvent<T> {
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes") //
|
|
||||||
private static final AtomicReferenceFieldUpdater<ChangeStreamEvent, Object> CONVERTED_UPDATER = AtomicReferenceFieldUpdater
|
|
||||||
.newUpdater(ChangeStreamEvent.class, Object.class, "converted");
|
|
||||||
|
|
||||||
private final @Nullable ChangeStreamDocument<Document> raw;
|
|
||||||
|
|
||||||
private final Class<T> targetType;
|
|
||||||
private final MongoConverter converter;
|
|
||||||
|
|
||||||
// accessed through CONVERTED_UPDATER.
|
|
||||||
private volatile @Nullable T converted;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param raw can be {@literal null}.
|
|
||||||
* @param targetType must not be {@literal null}.
|
|
||||||
* @param converter must not be {@literal null}.
|
|
||||||
*/
|
|
||||||
public ChangeStreamEvent(@Nullable ChangeStreamDocument<Document> raw, Class<T> targetType,
|
|
||||||
MongoConverter converter) {
|
|
||||||
|
|
||||||
this.raw = raw;
|
|
||||||
this.targetType = targetType;
|
|
||||||
this.converter = converter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the raw {@link ChangeStreamDocument} as emitted by the driver.
|
|
||||||
*
|
|
||||||
* @return can be {@literal null}.
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public ChangeStreamDocument<Document> getRaw() {
|
|
||||||
return raw;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the {@link ChangeStreamDocument#getClusterTime() cluster time} as {@link Instant} the event was emitted at.
|
|
||||||
*
|
|
||||||
* @return can be {@literal null}.
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public Instant getTimestamp() {
|
|
||||||
|
|
||||||
return getBsonTimestamp() != null ? converter.getConversionService().convert(raw.getClusterTime(), Instant.class)
|
|
||||||
: null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the {@link ChangeStreamDocument#getClusterTime() cluster time}.
|
|
||||||
*
|
|
||||||
* @return can be {@literal null}.
|
|
||||||
* @since 2.2
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public BsonTimestamp getBsonTimestamp() {
|
|
||||||
return raw != null ? raw.getClusterTime() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the {@link ChangeStreamDocument#getResumeToken() resume token} for this event.
|
|
||||||
*
|
|
||||||
* @return can be {@literal null}.
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public BsonValue getResumeToken() {
|
|
||||||
return raw != null ? raw.getResumeToken() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the {@link ChangeStreamDocument#getOperationType() operation type} for this event.
|
|
||||||
*
|
|
||||||
* @return can be {@literal null}.
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public OperationType getOperationType() {
|
|
||||||
return raw != null ? raw.getOperationType() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the database name the event was originated at.
|
|
||||||
*
|
|
||||||
* @return can be {@literal null}.
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public String getDatabaseName() {
|
|
||||||
return raw != null ? raw.getNamespace().getDatabaseName() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the collection name the event was originated at.
|
|
||||||
*
|
|
||||||
* @return can be {@literal null}.
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public String getCollectionName() {
|
|
||||||
return raw != null ? raw.getNamespace().getCollectionName() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the potentially converted {@link ChangeStreamDocument#getFullDocument()}.
|
|
||||||
*
|
|
||||||
* @return {@literal null} when {@link #getRaw()} or {@link ChangeStreamDocument#getFullDocument()} is
|
|
||||||
* {@literal null}.
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public T getBody() {
|
|
||||||
|
|
||||||
if (raw == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Document fullDocument = raw.getFullDocument();
|
|
||||||
|
|
||||||
if (fullDocument == null) {
|
|
||||||
return targetType.cast(fullDocument);
|
|
||||||
}
|
|
||||||
|
|
||||||
return getConverted(fullDocument);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private T getConverted(Document fullDocument) {
|
|
||||||
return (T) doGetConverted(fullDocument);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Object doGetConverted(Document fullDocument) {
|
|
||||||
|
|
||||||
Object result = CONVERTED_UPDATER.get(this);
|
|
||||||
|
|
||||||
if (result != null) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ClassUtils.isAssignable(Document.class, fullDocument.getClass())) {
|
|
||||||
|
|
||||||
result = converter.read(targetType, fullDocument);
|
|
||||||
return CONVERTED_UPDATER.compareAndSet(this, null, result) ? result : CONVERTED_UPDATER.get(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (converter.getConversionService().canConvert(fullDocument.getClass(), targetType)) {
|
|
||||||
|
|
||||||
result = converter.getConversionService().convert(fullDocument, targetType);
|
|
||||||
return CONVERTED_UPDATER.compareAndSet(this, null, result) ? result : CONVERTED_UPDATER.get(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException(String.format("No converter found capable of converting %s to %s",
|
|
||||||
fullDocument.getClass(), targetType));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see java.lang.Object#toString()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "ChangeStreamEvent {" + "raw=" + raw + ", targetType=" + targetType + '}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,292 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* 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 lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import org.bson.BsonTimestamp;
|
|
||||||
import org.bson.BsonValue;
|
|
||||||
import org.bson.Document;
|
|
||||||
import org.springframework.data.mongodb.core.aggregation.Aggregation;
|
|
||||||
import org.springframework.data.mongodb.core.query.Collation;
|
|
||||||
import org.springframework.lang.Nullable;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.util.ClassUtils;
|
|
||||||
import org.springframework.util.ObjectUtils;
|
|
||||||
|
|
||||||
import com.mongodb.client.model.changestream.ChangeStreamDocument;
|
|
||||||
import com.mongodb.client.model.changestream.FullDocument;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Options applicable to MongoDB <a href="https://docs.mongodb.com/manual/changeStreams/">Change Streams</a>. Intended
|
|
||||||
* to be used along with {@link org.springframework.data.mongodb.core.messaging.ChangeStreamRequest} in a sync world as
|
|
||||||
* well {@link ReactiveMongoOperations} if you prefer it that way.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @author Mark Paluch
|
|
||||||
* @since 2.1
|
|
||||||
*/
|
|
||||||
@EqualsAndHashCode
|
|
||||||
public class ChangeStreamOptions {
|
|
||||||
|
|
||||||
private @Nullable Object filter;
|
|
||||||
private @Nullable BsonValue resumeToken;
|
|
||||||
private @Nullable FullDocument fullDocumentLookup;
|
|
||||||
private @Nullable Collation collation;
|
|
||||||
private @Nullable Object resumeTimestamp;
|
|
||||||
|
|
||||||
protected ChangeStreamOptions() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {@link Optional#empty()} if not set.
|
|
||||||
*/
|
|
||||||
public Optional<Object> getFilter() {
|
|
||||||
return Optional.ofNullable(filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {@link Optional#empty()} if not set.
|
|
||||||
*/
|
|
||||||
public Optional<BsonValue> getResumeToken() {
|
|
||||||
return Optional.ofNullable(resumeToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {@link Optional#empty()} if not set.
|
|
||||||
*/
|
|
||||||
public Optional<FullDocument> getFullDocumentLookup() {
|
|
||||||
return Optional.ofNullable(fullDocumentLookup);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {@link Optional#empty()} if not set.
|
|
||||||
*/
|
|
||||||
public Optional<Collation> getCollation() {
|
|
||||||
return Optional.ofNullable(collation);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {@link Optional#empty()} if not set.
|
|
||||||
*/
|
|
||||||
public Optional<Instant> getResumeTimestamp() {
|
|
||||||
return Optional.ofNullable(resumeTimestamp).map(timestamp -> asTimestampOfType(timestamp, Instant.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {@link Optional#empty()} if not set.
|
|
||||||
* @since 2.2
|
|
||||||
*/
|
|
||||||
public Optional<BsonTimestamp> getResumeBsonTimestamp() {
|
|
||||||
return Optional.ofNullable(resumeTimestamp).map(timestamp -> asTimestampOfType(timestamp, BsonTimestamp.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return empty {@link ChangeStreamOptions}.
|
|
||||||
*/
|
|
||||||
public static ChangeStreamOptions empty() {
|
|
||||||
return ChangeStreamOptions.builder().build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain a shiny new {@link ChangeStreamOptionsBuilder} and start defining options in this fancy fluent way. Just
|
|
||||||
* don't forget to call {@link ChangeStreamOptionsBuilder#build() build()} when your're done.
|
|
||||||
*
|
|
||||||
* @return new instance of {@link ChangeStreamOptionsBuilder}.
|
|
||||||
*/
|
|
||||||
public static ChangeStreamOptionsBuilder builder() {
|
|
||||||
return new ChangeStreamOptionsBuilder();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <T> T asTimestampOfType(Object timestamp, Class<T> targetType) {
|
|
||||||
return targetType.cast(doGetTimestamp(timestamp, targetType));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <T> Object doGetTimestamp(Object timestamp, Class<T> targetType) {
|
|
||||||
|
|
||||||
if (ClassUtils.isAssignableValue(targetType, timestamp)) {
|
|
||||||
return timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (timestamp instanceof Instant) {
|
|
||||||
return new BsonTimestamp((int) ((Instant) timestamp).getEpochSecond(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (timestamp instanceof BsonTimestamp) {
|
|
||||||
return Instant.ofEpochSecond(((BsonTimestamp) timestamp).getTime());
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"o_O that should actually not happen. The timestamp should be an Instant or a BsonTimestamp but was "
|
|
||||||
+ ObjectUtils.nullSafeClassName(timestamp));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builder for creating {@link ChangeStreamOptions}.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 2.1
|
|
||||||
*/
|
|
||||||
public static class ChangeStreamOptionsBuilder {
|
|
||||||
|
|
||||||
private @Nullable Object filter;
|
|
||||||
private @Nullable BsonValue resumeToken;
|
|
||||||
private @Nullable FullDocument fullDocumentLookup;
|
|
||||||
private @Nullable Collation collation;
|
|
||||||
private @Nullable Object resumeTimestamp;
|
|
||||||
|
|
||||||
private ChangeStreamOptionsBuilder() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the collation to use.
|
|
||||||
*
|
|
||||||
* @param collation must not be {@literal null} nor {@literal empty}.
|
|
||||||
* @return this.
|
|
||||||
*/
|
|
||||||
public ChangeStreamOptionsBuilder collation(Collation collation) {
|
|
||||||
|
|
||||||
Assert.notNull(collation, "Collation must not be null nor empty!");
|
|
||||||
|
|
||||||
this.collation = collation;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the filter to apply.
|
|
||||||
* <p/>
|
|
||||||
* Fields on aggregation expression root level are prefixed to map to fields contained in
|
|
||||||
* {@link ChangeStreamDocument#getFullDocument() fullDocument}. However {@literal operationType}, {@literal ns},
|
|
||||||
* {@literal documentKey} and {@literal fullDocument} are reserved words that will be omitted, and therefore taken
|
|
||||||
* as given, during the mapping procedure. You may want to have a look at the
|
|
||||||
* <a href="https://docs.mongodb.com/manual/reference/change-events/">structure of Change Events</a>.
|
|
||||||
* <p/>
|
|
||||||
* Use {@link org.springframework.data.mongodb.core.aggregation.TypedAggregation} to ensure filter expressions are
|
|
||||||
* mapped to domain type fields.
|
|
||||||
*
|
|
||||||
* @param filter the {@link Aggregation Aggregation pipeline} to apply for filtering events. Must not be
|
|
||||||
* {@literal null}.
|
|
||||||
* @return this.
|
|
||||||
*/
|
|
||||||
public ChangeStreamOptionsBuilder filter(Aggregation filter) {
|
|
||||||
|
|
||||||
Assert.notNull(filter, "Filter must not be null!");
|
|
||||||
|
|
||||||
this.filter = filter;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the plain filter chain to apply.
|
|
||||||
*
|
|
||||||
* @param filter must not be {@literal null} nor contain {@literal null} values.
|
|
||||||
* @return this.
|
|
||||||
*/
|
|
||||||
public ChangeStreamOptionsBuilder filter(Document... filter) {
|
|
||||||
|
|
||||||
Assert.noNullElements(filter, "Filter must not contain null values");
|
|
||||||
|
|
||||||
this.filter = Arrays.asList(filter);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the resume token (typically a {@link org.bson.BsonDocument} containing a {@link org.bson.BsonBinary binary
|
|
||||||
* token}) after which to start with listening.
|
|
||||||
*
|
|
||||||
* @param resumeToken must not be {@literal null}.
|
|
||||||
* @return this.
|
|
||||||
*/
|
|
||||||
public ChangeStreamOptionsBuilder resumeToken(BsonValue resumeToken) {
|
|
||||||
|
|
||||||
Assert.notNull(resumeToken, "ResumeToken must not be null!");
|
|
||||||
|
|
||||||
this.resumeToken = resumeToken;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the {@link FullDocument} lookup to {@link FullDocument#UPDATE_LOOKUP}.
|
|
||||||
*
|
|
||||||
* @return this.
|
|
||||||
* @see #fullDocumentLookup(FullDocument)
|
|
||||||
*/
|
|
||||||
public ChangeStreamOptionsBuilder returnFullDocumentOnUpdate() {
|
|
||||||
return fullDocumentLookup(FullDocument.UPDATE_LOOKUP);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the {@link FullDocument} lookup to use.
|
|
||||||
*
|
|
||||||
* @param lookup must not be {@literal null}.
|
|
||||||
* @return this.
|
|
||||||
*/
|
|
||||||
public ChangeStreamOptionsBuilder fullDocumentLookup(FullDocument lookup) {
|
|
||||||
|
|
||||||
Assert.notNull(lookup, "Lookup must not be null!");
|
|
||||||
|
|
||||||
this.fullDocumentLookup = lookup;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the cluster time to resume from.
|
|
||||||
*
|
|
||||||
* @param resumeTimestamp must not be {@literal null}.
|
|
||||||
* @return this.
|
|
||||||
*/
|
|
||||||
public ChangeStreamOptionsBuilder resumeAt(Instant resumeTimestamp) {
|
|
||||||
|
|
||||||
Assert.notNull(resumeTimestamp, "ResumeTimestamp must not be null!");
|
|
||||||
|
|
||||||
this.resumeTimestamp = resumeTimestamp;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the cluster time to resume from.
|
|
||||||
*
|
|
||||||
* @param resumeTimestamp must not be {@literal null}.
|
|
||||||
* @return this.
|
|
||||||
* @since 2.2
|
|
||||||
*/
|
|
||||||
public ChangeStreamOptionsBuilder resumeAt(BsonTimestamp resumeTimestamp) {
|
|
||||||
|
|
||||||
Assert.notNull(resumeTimestamp, "ResumeTimestamp must not be null!");
|
|
||||||
|
|
||||||
this.resumeTimestamp = resumeTimestamp;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the built {@link ChangeStreamOptions}
|
|
||||||
*/
|
|
||||||
public ChangeStreamOptions build() {
|
|
||||||
|
|
||||||
ChangeStreamOptions options = new ChangeStreamOptions();
|
|
||||||
|
|
||||||
options.filter = filter;
|
|
||||||
options.resumeToken = resumeToken;
|
|
||||||
options.fullDocumentLookup = fullDocumentLookup;
|
|
||||||
options.collation = collation;
|
|
||||||
options.resumeTimestamp = resumeTimestamp;
|
|
||||||
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -15,32 +15,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.mongodb.core;
|
package org.springframework.data.mongodb.core;
|
||||||
|
|
||||||
import org.bson.Document;
|
import com.mongodb.DBCollection;
|
||||||
import org.springframework.dao.DataAccessException;
|
|
||||||
import org.springframework.lang.Nullable;
|
|
||||||
|
|
||||||
import com.mongodb.MongoException;
|
import com.mongodb.MongoException;
|
||||||
import com.mongodb.client.MongoCollection;
|
import org.springframework.dao.DataAccessException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback interface for executing actions against a {@link MongoCollection}.
|
|
||||||
*
|
|
||||||
* @author Mark Pollak
|
|
||||||
* @author Grame Rocher
|
|
||||||
* @author Oliver Gierke
|
|
||||||
* @author John Brisbin
|
|
||||||
* @auhtor Christoph Strobl
|
|
||||||
* @since 1.0
|
|
||||||
*/
|
|
||||||
public interface CollectionCallback<T> {
|
public interface CollectionCallback<T> {
|
||||||
|
|
||||||
/**
|
T doInCollection(DBCollection collection) throws MongoException, DataAccessException;
|
||||||
* @param collection never {@literal null}.
|
|
||||||
* @return can be {@literal null}.
|
|
||||||
* @throws MongoException
|
|
||||||
* @throws DataAccessException
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
T doInCollection(MongoCollection<Document> collection) throws MongoException, DataAccessException;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -15,383 +15,56 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.mongodb.core;
|
package org.springframework.data.mongodb.core;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import org.springframework.data.mongodb.core.query.Collation;
|
|
||||||
import org.springframework.data.mongodb.core.schema.MongoJsonSchema;
|
|
||||||
import org.springframework.data.mongodb.core.validation.Validator;
|
|
||||||
import org.springframework.data.util.Optionals;
|
|
||||||
import org.springframework.lang.Nullable;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
import com.mongodb.client.model.ValidationAction;
|
|
||||||
import com.mongodb.client.model.ValidationLevel;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides a simple wrapper to encapsulate the variety of settings you can use when creating a collection.
|
* Provides a simple wrapper to encapsulate the variety of settings you can use when creating a collection.
|
||||||
*
|
*
|
||||||
* @author Thomas Risberg
|
* @author Thomas Risberg
|
||||||
* @author Christoph Strobl
|
|
||||||
* @author Mark Paluch
|
|
||||||
* @author Andreas Zink
|
|
||||||
*/
|
*/
|
||||||
public class CollectionOptions {
|
public class CollectionOptions {
|
||||||
|
|
||||||
private @Nullable Long maxDocuments;
|
private Integer maxDocuments;
|
||||||
private @Nullable Long size;
|
|
||||||
private @Nullable Boolean capped;
|
private Integer size;
|
||||||
private @Nullable Collation collation;
|
|
||||||
private ValidationOptions validationOptions;
|
private Boolean capped;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new <code>CollectionOptions</code> instance.
|
* Constructs a new <code>CollectionOptions</code> instance.
|
||||||
*
|
*
|
||||||
* @param size the collection size in bytes, this data space is preallocated. Can be {@literal null}.
|
* @param size the collection size in bytes, this data space is preallocated
|
||||||
* @param maxDocuments the maximum number of documents in the collection. Can be {@literal null}.
|
* @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),
|
* @param capped true to created a "capped" collection (fixed size with auto-FIFO behavior based on insertion order),
|
||||||
* false otherwise. Can be {@literal null}.
|
* false otherwise.
|
||||||
* @deprecated since 2.0 please use {@link CollectionOptions#empty()} as entry point.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
public CollectionOptions(Integer size, Integer maxDocuments, Boolean capped) {
|
||||||
public CollectionOptions(@Nullable Long size, @Nullable Long maxDocuments, @Nullable Boolean capped) {
|
super();
|
||||||
this(size, maxDocuments, capped, null, ValidationOptions.none());
|
|
||||||
}
|
|
||||||
|
|
||||||
private CollectionOptions(@Nullable Long size, @Nullable Long maxDocuments, @Nullable Boolean capped,
|
|
||||||
@Nullable Collation collation, ValidationOptions validationOptions) {
|
|
||||||
|
|
||||||
this.maxDocuments = maxDocuments;
|
this.maxDocuments = maxDocuments;
|
||||||
this.size = size;
|
this.size = size;
|
||||||
this.capped = capped;
|
this.capped = capped;
|
||||||
this.collation = collation;
|
|
||||||
this.validationOptions = validationOptions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public Integer getMaxDocuments() {
|
||||||
* Create new {@link CollectionOptions} by just providing the {@link Collation} to use.
|
return maxDocuments;
|
||||||
*
|
|
||||||
* @param collation must not be {@literal null}.
|
|
||||||
* @return new {@link CollectionOptions}.
|
|
||||||
* @since 2.0
|
|
||||||
*/
|
|
||||||
public static CollectionOptions just(Collation collation) {
|
|
||||||
|
|
||||||
Assert.notNull(collation, "Collation must not be null!");
|
|
||||||
|
|
||||||
return new CollectionOptions(null, null, null, collation, ValidationOptions.none());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public void setMaxDocuments(Integer maxDocuments) {
|
||||||
* Create new empty {@link CollectionOptions}.
|
this.maxDocuments = maxDocuments;
|
||||||
*
|
|
||||||
* @return new {@link CollectionOptions}.
|
|
||||||
* @since 2.0
|
|
||||||
*/
|
|
||||||
public static CollectionOptions empty() {
|
|
||||||
return new CollectionOptions(null, null, null, null, ValidationOptions.none());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public Integer getSize() {
|
||||||
* Create new {@link CollectionOptions} with already given settings and capped set to {@literal true}. <br />
|
return size;
|
||||||
* <strong>NOTE</strong> Using capped collections requires defining {@link #size(int)}.
|
|
||||||
*
|
|
||||||
* @return new {@link CollectionOptions}.
|
|
||||||
* @since 2.0
|
|
||||||
*/
|
|
||||||
public CollectionOptions capped() {
|
|
||||||
return new CollectionOptions(size, maxDocuments, true, collation, validationOptions);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public void setSize(Integer size) {
|
||||||
* Create new {@link CollectionOptions} with already given settings and {@code maxDocuments} set to given value.
|
this.size = size;
|
||||||
*
|
|
||||||
* @param maxDocuments can be {@literal null}.
|
|
||||||
* @return new {@link CollectionOptions}.
|
|
||||||
* @since 2.0
|
|
||||||
*/
|
|
||||||
public CollectionOptions maxDocuments(long maxDocuments) {
|
|
||||||
return new CollectionOptions(size, maxDocuments, capped, collation, validationOptions);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public Boolean getCapped() {
|
||||||
* Create new {@link CollectionOptions} with already given settings and {@code size} set to given value.
|
return capped;
|
||||||
*
|
|
||||||
* @param size can be {@literal null}.
|
|
||||||
* @return new {@link CollectionOptions}.
|
|
||||||
* @since 2.0
|
|
||||||
*/
|
|
||||||
public CollectionOptions size(long size) {
|
|
||||||
return new CollectionOptions(size, maxDocuments, capped, collation, validationOptions);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public void setCapped(Boolean capped) {
|
||||||
* Create new {@link CollectionOptions} with already given settings and {@code collation} set to given value.
|
this.capped = capped;
|
||||||
*
|
|
||||||
* @param collation can be {@literal null}.
|
|
||||||
* @return new {@link CollectionOptions}.
|
|
||||||
* @since 2.0
|
|
||||||
*/
|
|
||||||
public CollectionOptions collation(@Nullable Collation collation) {
|
|
||||||
return new CollectionOptions(size, maxDocuments, capped, collation, validationOptions);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create new {@link CollectionOptions} with already given settings and {@code validationOptions} set to given
|
|
||||||
* {@link MongoJsonSchema}.
|
|
||||||
*
|
|
||||||
* @param schema can be {@literal null}.
|
|
||||||
* @return new {@link CollectionOptions}.
|
|
||||||
* @since 2.1
|
|
||||||
*/
|
|
||||||
public CollectionOptions schema(@Nullable MongoJsonSchema schema) {
|
|
||||||
return validator(Validator.schema(schema));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create new {@link CollectionOptions} with already given settings and {@code validationOptions} set to given
|
|
||||||
* {@link Validator}.
|
|
||||||
*
|
|
||||||
* @param validator can be {@literal null}.
|
|
||||||
* @return new {@link CollectionOptions}.
|
|
||||||
* @since 2.1
|
|
||||||
*/
|
|
||||||
public CollectionOptions validator(@Nullable Validator validator) {
|
|
||||||
return validation(validationOptions.validator(validator));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create new {@link CollectionOptions} with already given settings and {@code validationLevel} set to
|
|
||||||
* {@link ValidationLevel#OFF}.
|
|
||||||
*
|
|
||||||
* @return new {@link CollectionOptions}.
|
|
||||||
* @since 2.1
|
|
||||||
*/
|
|
||||||
public CollectionOptions disableValidation() {
|
|
||||||
return schemaValidationLevel(ValidationLevel.OFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create new {@link CollectionOptions} with already given settings and {@code validationLevel} set to
|
|
||||||
* {@link ValidationLevel#STRICT}.
|
|
||||||
*
|
|
||||||
* @return new {@link CollectionOptions}.
|
|
||||||
* @since 2.1
|
|
||||||
*/
|
|
||||||
public CollectionOptions strictValidation() {
|
|
||||||
return schemaValidationLevel(ValidationLevel.STRICT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create new {@link CollectionOptions} with already given settings and {@code validationLevel} set to
|
|
||||||
* {@link ValidationLevel#MODERATE}.
|
|
||||||
*
|
|
||||||
* @return new {@link CollectionOptions}.
|
|
||||||
* @since 2.1
|
|
||||||
*/
|
|
||||||
public CollectionOptions moderateValidation() {
|
|
||||||
return schemaValidationLevel(ValidationLevel.MODERATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create new {@link CollectionOptions} with already given settings and {@code validationAction} set to
|
|
||||||
* {@link ValidationAction#WARN}.
|
|
||||||
*
|
|
||||||
* @return new {@link CollectionOptions}.
|
|
||||||
* @since 2.1
|
|
||||||
*/
|
|
||||||
public CollectionOptions warnOnValidationError() {
|
|
||||||
return schemaValidationAction(ValidationAction.WARN);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create new {@link CollectionOptions} with already given settings and {@code validationAction} set to
|
|
||||||
* {@link ValidationAction#ERROR}.
|
|
||||||
*
|
|
||||||
* @return new {@link CollectionOptions}.
|
|
||||||
* @since 2.1
|
|
||||||
*/
|
|
||||||
public CollectionOptions failOnValidationError() {
|
|
||||||
return schemaValidationAction(ValidationAction.ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create new {@link CollectionOptions} with already given settings and {@code validationLevel} set given
|
|
||||||
* {@link ValidationLevel}.
|
|
||||||
*
|
|
||||||
* @param validationLevel must not be {@literal null}.
|
|
||||||
* @return new {@link CollectionOptions}.
|
|
||||||
* @since 2.1
|
|
||||||
*/
|
|
||||||
public CollectionOptions schemaValidationLevel(ValidationLevel validationLevel) {
|
|
||||||
|
|
||||||
Assert.notNull(validationLevel, "ValidationLevel must not be null!");
|
|
||||||
return validation(validationOptions.validationLevel(validationLevel));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create new {@link CollectionOptions} with already given settings and {@code validationAction} set given
|
|
||||||
* {@link ValidationAction}.
|
|
||||||
*
|
|
||||||
* @param validationAction must not be {@literal null}.
|
|
||||||
* @return new {@link CollectionOptions}.
|
|
||||||
* @since 2.1
|
|
||||||
*/
|
|
||||||
public CollectionOptions schemaValidationAction(ValidationAction validationAction) {
|
|
||||||
|
|
||||||
Assert.notNull(validationAction, "ValidationAction must not be null!");
|
|
||||||
return validation(validationOptions.validationAction(validationAction));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create new {@link CollectionOptions} with the given {@link ValidationOptions}.
|
|
||||||
*
|
|
||||||
* @param validationOptions must not be {@literal null}. Use {@link ValidationOptions#none()} to remove validation.
|
|
||||||
* @return new {@link CollectionOptions}.
|
|
||||||
* @since 2.1
|
|
||||||
*/
|
|
||||||
public CollectionOptions validation(ValidationOptions validationOptions) {
|
|
||||||
|
|
||||||
Assert.notNull(validationOptions, "ValidationOptions must not be null!");
|
|
||||||
return new CollectionOptions(size, maxDocuments, capped, collation, validationOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the max number of documents the collection should be limited to.
|
|
||||||
*
|
|
||||||
* @return {@link Optional#empty()} if not set.
|
|
||||||
*/
|
|
||||||
public Optional<Long> getMaxDocuments() {
|
|
||||||
return Optional.ofNullable(maxDocuments);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the {@literal size} in bytes the collection should be limited to.
|
|
||||||
*
|
|
||||||
* @return {@link Optional#empty()} if not set.
|
|
||||||
*/
|
|
||||||
public Optional<Long> getSize() {
|
|
||||||
return Optional.ofNullable(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get if the collection should be capped.
|
|
||||||
*
|
|
||||||
* @return {@link Optional#empty()} if not set.
|
|
||||||
* @since 2.0
|
|
||||||
*/
|
|
||||||
public Optional<Boolean> getCapped() {
|
|
||||||
return Optional.ofNullable(capped);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the {@link Collation} settings.
|
|
||||||
*
|
|
||||||
* @return {@link Optional#empty()} if not set.
|
|
||||||
* @since 2.0
|
|
||||||
*/
|
|
||||||
public Optional<Collation> getCollation() {
|
|
||||||
return Optional.ofNullable(collation);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the {@link MongoJsonSchema} for the collection.
|
|
||||||
*
|
|
||||||
* @return {@link Optional#empty()} if not set.
|
|
||||||
* @since 2.1
|
|
||||||
*/
|
|
||||||
public Optional<ValidationOptions> getValidationOptions() {
|
|
||||||
return validationOptions.isEmpty() ? Optional.empty() : Optional.of(validationOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encapsulation of ValidationOptions options.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @author Andreas Zink
|
|
||||||
* @since 2.1
|
|
||||||
*/
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public static class ValidationOptions {
|
|
||||||
|
|
||||||
private static final ValidationOptions NONE = new ValidationOptions(null, null, null);
|
|
||||||
|
|
||||||
private final @Nullable Validator validator;
|
|
||||||
private final @Nullable ValidationLevel validationLevel;
|
|
||||||
private final @Nullable ValidationAction validationAction;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an empty {@link ValidationOptions}.
|
|
||||||
*
|
|
||||||
* @return never {@literal null}.
|
|
||||||
*/
|
|
||||||
public static ValidationOptions none() {
|
|
||||||
return NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Define the {@link Validator} to be used for document validation.
|
|
||||||
*
|
|
||||||
* @param validator can be {@literal null}.
|
|
||||||
* @return new instance of {@link ValidationOptions}.
|
|
||||||
*/
|
|
||||||
public ValidationOptions validator(@Nullable Validator validator) {
|
|
||||||
return new ValidationOptions(validator, validationLevel, validationAction);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Define the validation level to apply.
|
|
||||||
*
|
|
||||||
* @param validationLevel can be {@literal null}.
|
|
||||||
* @return new instance of {@link ValidationOptions}.
|
|
||||||
*/
|
|
||||||
public ValidationOptions validationLevel(ValidationLevel validationLevel) {
|
|
||||||
return new ValidationOptions(validator, validationLevel, validationAction);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Define the validation action to take.
|
|
||||||
*
|
|
||||||
* @param validationAction can be {@literal null}.
|
|
||||||
* @return new instance of {@link ValidationOptions}.
|
|
||||||
*/
|
|
||||||
public ValidationOptions validationAction(ValidationAction validationAction) {
|
|
||||||
return new ValidationOptions(validator, validationLevel, validationAction);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the {@link Validator} to use.
|
|
||||||
*
|
|
||||||
* @return never {@literal null}.
|
|
||||||
*/
|
|
||||||
public Optional<Validator> getValidator() {
|
|
||||||
return Optional.ofNullable(validator);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the {@code validationLevel} to apply.
|
|
||||||
*
|
|
||||||
* @return {@link Optional#empty()} if not set.
|
|
||||||
*/
|
|
||||||
public Optional<ValidationLevel> getValidationLevel() {
|
|
||||||
return Optional.ofNullable(validationLevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the {@code validationAction} to perform.
|
|
||||||
*
|
|
||||||
* @return @return {@link Optional#empty()} if not set.
|
|
||||||
*/
|
|
||||||
public Optional<ValidationAction> getValidationAction() {
|
|
||||||
return Optional.ofNullable(validationAction);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {@literal true} if no arguments set.
|
|
||||||
*/
|
|
||||||
boolean isEmpty() {
|
|
||||||
return !Optionals.isAnyPresent(getValidator(), getValidationAction(), getValidationLevel());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -15,22 +15,19 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.mongodb.core;
|
package org.springframework.data.mongodb.core;
|
||||||
|
|
||||||
import org.bson.Document;
|
import com.mongodb.DBCursor;
|
||||||
|
|
||||||
import com.mongodb.client.FindIterable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple callback interface to allow customization of a {@link FindIterable}.
|
* Simple callback interface to allow customization of a {@link DBCursor}.
|
||||||
*
|
*
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Christoph Strobl
|
|
||||||
*/
|
*/
|
||||||
interface CursorPreparer {
|
interface CursorPreparer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare the given cursor (apply limits, skips and so on). Returns the prepared cursor.
|
* Prepare the given cursor (apply limits, skips and so on). Returns the prepared cursor.
|
||||||
*
|
*
|
||||||
* @param cursor
|
* @param cursor
|
||||||
*/
|
*/
|
||||||
FindIterable<Document> prepare(FindIterable<Document> cursor);
|
DBCursor prepare(DBCursor cursor);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -15,30 +15,11 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.mongodb.core;
|
package org.springframework.data.mongodb.core;
|
||||||
|
|
||||||
import org.springframework.dao.DataAccessException;
|
import com.mongodb.DB;
|
||||||
import org.springframework.lang.Nullable;
|
|
||||||
|
|
||||||
import com.mongodb.MongoException;
|
import com.mongodb.MongoException;
|
||||||
import com.mongodb.client.MongoDatabase;
|
import org.springframework.dao.DataAccessException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback interface for executing actions against a {@link MongoDatabase}.
|
|
||||||
*
|
|
||||||
* @author Mark Pollak
|
|
||||||
* @author Graeme Rocher
|
|
||||||
* @author Thomas Risberg
|
|
||||||
* @author Oliver Gierke
|
|
||||||
* @author John Brisbin
|
|
||||||
* @author Christoph Strobl
|
|
||||||
*/
|
|
||||||
public interface DbCallback<T> {
|
public interface DbCallback<T> {
|
||||||
|
|
||||||
/**
|
T doInDB(DB db) throws MongoException, DataAccessException;
|
||||||
* @param db must not be {@literal null}.
|
|
||||||
* @return can be {@literal null}.
|
|
||||||
* @throws MongoException
|
|
||||||
* @throws DataAccessException
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
T doInDB(MongoDatabase db) throws MongoException, DataAccessException;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package org.springframework.data.mongodb.core;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import com.mongodb.DB;
|
||||||
|
import org.springframework.transaction.support.ResourceHolderSupport;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
class DbHolder extends ResourceHolderSupport {
|
||||||
|
private static final Object DEFAULT_KEY = new Object();
|
||||||
|
|
||||||
|
private final Map<Object, DB> dbMap = new ConcurrentHashMap<Object, DB>();
|
||||||
|
|
||||||
|
public DbHolder(DB db) {
|
||||||
|
addDB(db);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DbHolder(Object key, DB db) {
|
||||||
|
addDB(key, db);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DB getDB() {
|
||||||
|
return getDB(DEFAULT_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DB getDB(Object key) {
|
||||||
|
return this.dbMap.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DB getAnyDB() {
|
||||||
|
if (!this.dbMap.isEmpty()) {
|
||||||
|
return this.dbMap.values().iterator().next();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addDB(DB session) {
|
||||||
|
addDB(DEFAULT_KEY, session);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addDB(Object key, DB session) {
|
||||||
|
Assert.notNull(key, "Key must not be null");
|
||||||
|
Assert.notNull(session, "DB must not be null");
|
||||||
|
this.dbMap.put(key, session);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DB removeDB(Object key) {
|
||||||
|
return this.dbMap.remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsDB(DB session) {
|
||||||
|
return this.dbMap.containsValue(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return this.dbMap.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean doesNotHoldNonDefaultDB() {
|
||||||
|
synchronized (this.dbMap) {
|
||||||
|
return this.dbMap.isEmpty() || (this.dbMap.size() == 1 && this.dbMap.containsKey(DEFAULT_KEY));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user