Compare commits
90 Commits
issue/reac
...
1.10.0.REL
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
BIN
.mvn/wrapper/maven-wrapper.jar
vendored
BIN
.mvn/wrapper/maven-wrapper.jar
vendored
Binary file not shown.
1
.mvn/wrapper/maven-wrapper.properties
vendored
1
.mvn/wrapper/maven-wrapper.properties
vendored
@@ -1 +0,0 @@
|
|||||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip
|
|
||||||
33
.travis.yml
33
.travis.yml
@@ -3,33 +3,38 @@ language: java
|
|||||||
jdk:
|
jdk:
|
||||||
- oraclejdk8
|
- oraclejdk8
|
||||||
|
|
||||||
before_install:
|
before_script:
|
||||||
- mkdir -p downloads
|
- mongod --version
|
||||||
- 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:
|
env:
|
||||||
matrix:
|
matrix:
|
||||||
- PROFILE=ci
|
- PROFILE=ci
|
||||||
global:
|
- PROFILE=mongo-next
|
||||||
- MONGO_VERSION=4.0.0
|
- PROFILE=mongo3
|
||||||
|
- PROFILE=mongo3-next
|
||||||
|
- PROFILE=mongo31
|
||||||
|
- PROFILE=mongo32
|
||||||
|
- PROFILE=mongo33
|
||||||
|
- PROFILE=mongo34
|
||||||
|
- PROFILE=mongo34-next
|
||||||
|
|
||||||
|
# Current MongoDB version is 2.4.2 as of 2016-04, see https://github.com/travis-ci/travis-ci/issues/3694
|
||||||
|
# apt-get starts a MongoDB instance so it's not started using before_script
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
|
sources:
|
||||||
|
- mongodb-3.4-precise
|
||||||
packages:
|
packages:
|
||||||
- oracle-java8-installer
|
- mongodb-org-server
|
||||||
|
- mongodb-org-shell
|
||||||
|
- oracle-java8-installer
|
||||||
|
|
||||||
sudo: false
|
sudo: false
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
directories:
|
directories:
|
||||||
- $HOME/.m2
|
- $HOME/.m2
|
||||||
- downloads
|
|
||||||
|
install: true
|
||||||
|
|
||||||
script: "mvn clean dependency:list test -P${PROFILE} -Dsort"
|
script: "mvn clean dependency:list test -P${PROFILE} -Dsort"
|
||||||
|
|||||||
38
README.md
38
README.md
@@ -83,7 +83,7 @@ You can have Spring automatically create a proxy for the interface by using the
|
|||||||
class ApplicationConfig extends AbstractMongoConfiguration {
|
class ApplicationConfig extends AbstractMongoConfiguration {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MongoClient mongoClient() throws Exception {
|
public Mongo mongo() throws Exception {
|
||||||
return new MongoClient();
|
return new MongoClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,42 +138,6 @@ public class MyService {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 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
|
## Contributing to Spring Data
|
||||||
|
|
||||||
Here are some ways for you to get involved in the community:
|
Here are some ways for you to get involved in the community:
|
||||||
|
|||||||
@@ -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 https://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 https://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/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>
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
lombok.nonNull.exceptionType = IllegalArgumentException
|
|
||||||
lombok.log.fieldName = LOG
|
|
||||||
286
mvnw
vendored
286
mvnw
vendored
@@ -1,286 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# ----------------------------------------------------------------------------
|
|
||||||
# Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
# or more contributor license agreements. See the NOTICE file
|
|
||||||
# distributed with this work for additional information
|
|
||||||
# regarding copyright ownership. The ASF licenses this file
|
|
||||||
# to you under the Apache License, Version 2.0 (the
|
|
||||||
# "License"); you may not use this file except in compliance
|
|
||||||
# with the License. You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing,
|
|
||||||
# software distributed under the License is distributed on an
|
|
||||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
# KIND, either express or implied. See the License for the
|
|
||||||
# specific language governing permissions and limitations
|
|
||||||
# under the License.
|
|
||||||
# ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------
|
|
||||||
# Maven2 Start Up Batch script
|
|
||||||
#
|
|
||||||
# Required ENV vars:
|
|
||||||
# ------------------
|
|
||||||
# JAVA_HOME - location of a JDK home dir
|
|
||||||
#
|
|
||||||
# Optional ENV vars
|
|
||||||
# -----------------
|
|
||||||
# M2_HOME - location of maven2's installed home dir
|
|
||||||
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
|
||||||
# e.g. to debug Maven itself, use
|
|
||||||
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
|
||||||
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
|
||||||
# ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
if [ -z "$MAVEN_SKIP_RC" ] ; then
|
|
||||||
|
|
||||||
if [ -f /etc/mavenrc ] ; then
|
|
||||||
. /etc/mavenrc
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -f "$HOME/.mavenrc" ] ; then
|
|
||||||
. "$HOME/.mavenrc"
|
|
||||||
fi
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
# OS specific support. $var _must_ be set to either true or false.
|
|
||||||
cygwin=false;
|
|
||||||
darwin=false;
|
|
||||||
mingw=false
|
|
||||||
case "`uname`" in
|
|
||||||
CYGWIN*) cygwin=true ;;
|
|
||||||
MINGW*) mingw=true;;
|
|
||||||
Darwin*) darwin=true
|
|
||||||
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
|
|
||||||
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
|
|
||||||
if [ -z "$JAVA_HOME" ]; then
|
|
||||||
if [ -x "/usr/libexec/java_home" ]; then
|
|
||||||
export JAVA_HOME="`/usr/libexec/java_home`"
|
|
||||||
else
|
|
||||||
export JAVA_HOME="/Library/Java/Home"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [ -z "$JAVA_HOME" ] ; then
|
|
||||||
if [ -r /etc/gentoo-release ] ; then
|
|
||||||
JAVA_HOME=`java-config --jre-home`
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$M2_HOME" ] ; then
|
|
||||||
## resolve links - $0 may be a link to maven's home
|
|
||||||
PRG="$0"
|
|
||||||
|
|
||||||
# need this for relative symlinks
|
|
||||||
while [ -h "$PRG" ] ; do
|
|
||||||
ls=`ls -ld "$PRG"`
|
|
||||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
|
||||||
if expr "$link" : '/.*' > /dev/null; then
|
|
||||||
PRG="$link"
|
|
||||||
else
|
|
||||||
PRG="`dirname "$PRG"`/$link"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
saveddir=`pwd`
|
|
||||||
|
|
||||||
M2_HOME=`dirname "$PRG"`/..
|
|
||||||
|
|
||||||
# make it fully qualified
|
|
||||||
M2_HOME=`cd "$M2_HOME" && pwd`
|
|
||||||
|
|
||||||
cd "$saveddir"
|
|
||||||
# echo Using m2 at $M2_HOME
|
|
||||||
fi
|
|
||||||
|
|
||||||
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
|
||||||
if $cygwin ; then
|
|
||||||
[ -n "$M2_HOME" ] &&
|
|
||||||
M2_HOME=`cygpath --unix "$M2_HOME"`
|
|
||||||
[ -n "$JAVA_HOME" ] &&
|
|
||||||
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
|
||||||
[ -n "$CLASSPATH" ] &&
|
|
||||||
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
|
|
||||||
fi
|
|
||||||
|
|
||||||
# For Mingw, ensure paths are in UNIX format before anything is touched
|
|
||||||
if $mingw ; then
|
|
||||||
[ -n "$M2_HOME" ] &&
|
|
||||||
M2_HOME="`(cd "$M2_HOME"; pwd)`"
|
|
||||||
[ -n "$JAVA_HOME" ] &&
|
|
||||||
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
|
|
||||||
# TODO classpath?
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$JAVA_HOME" ]; then
|
|
||||||
javaExecutable="`which javac`"
|
|
||||||
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
|
|
||||||
# readlink(1) is not available as standard on Solaris 10.
|
|
||||||
readLink=`which readlink`
|
|
||||||
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
|
|
||||||
if $darwin ; then
|
|
||||||
javaHome="`dirname \"$javaExecutable\"`"
|
|
||||||
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
|
|
||||||
else
|
|
||||||
javaExecutable="`readlink -f \"$javaExecutable\"`"
|
|
||||||
fi
|
|
||||||
javaHome="`dirname \"$javaExecutable\"`"
|
|
||||||
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
|
|
||||||
JAVA_HOME="$javaHome"
|
|
||||||
export JAVA_HOME
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$JAVACMD" ] ; then
|
|
||||||
if [ -n "$JAVA_HOME" ] ; then
|
|
||||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
|
||||||
# IBM's JDK on AIX uses strange locations for the executables
|
|
||||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
|
||||||
else
|
|
||||||
JAVACMD="$JAVA_HOME/bin/java"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
JAVACMD="`which java`"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -x "$JAVACMD" ] ; then
|
|
||||||
echo "Error: JAVA_HOME is not defined correctly." >&2
|
|
||||||
echo " We cannot execute $JAVACMD" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$JAVA_HOME" ] ; then
|
|
||||||
echo "Warning: JAVA_HOME environment variable is not set."
|
|
||||||
fi
|
|
||||||
|
|
||||||
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
|
|
||||||
|
|
||||||
# traverses directory structure from process work directory to filesystem root
|
|
||||||
# first directory with .mvn subdirectory is considered project base directory
|
|
||||||
find_maven_basedir() {
|
|
||||||
|
|
||||||
if [ -z "$1" ]
|
|
||||||
then
|
|
||||||
echo "Path not specified to find_maven_basedir"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
basedir="$1"
|
|
||||||
wdir="$1"
|
|
||||||
while [ "$wdir" != '/' ] ; do
|
|
||||||
if [ -d "$wdir"/.mvn ] ; then
|
|
||||||
basedir=$wdir
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
|
|
||||||
if [ -d "${wdir}" ]; then
|
|
||||||
wdir=`cd "$wdir/.."; pwd`
|
|
||||||
fi
|
|
||||||
# end of workaround
|
|
||||||
done
|
|
||||||
echo "${basedir}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# concatenates all lines of a file
|
|
||||||
concat_lines() {
|
|
||||||
if [ -f "$1" ]; then
|
|
||||||
echo "$(tr -s '\n' ' ' < "$1")"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
BASE_DIR=`find_maven_basedir "$(pwd)"`
|
|
||||||
if [ -z "$BASE_DIR" ]; then
|
|
||||||
exit 1;
|
|
||||||
fi
|
|
||||||
|
|
||||||
##########################################################################################
|
|
||||||
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
|
||||||
# This allows using the maven wrapper in projects that prohibit checking in binary data.
|
|
||||||
##########################################################################################
|
|
||||||
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
|
|
||||||
if [ "$MVNW_VERBOSE" = true ]; then
|
|
||||||
echo "Found .mvn/wrapper/maven-wrapper.jar"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
if [ "$MVNW_VERBOSE" = true ]; then
|
|
||||||
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
|
|
||||||
fi
|
|
||||||
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
|
|
||||||
while IFS="=" read key value; do
|
|
||||||
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
|
|
||||||
esac
|
|
||||||
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
|
|
||||||
if [ "$MVNW_VERBOSE" = true ]; then
|
|
||||||
echo "Downloading from: $jarUrl"
|
|
||||||
fi
|
|
||||||
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
|
|
||||||
|
|
||||||
if command -v wget > /dev/null; then
|
|
||||||
if [ "$MVNW_VERBOSE" = true ]; then
|
|
||||||
echo "Found wget ... using wget"
|
|
||||||
fi
|
|
||||||
wget "$jarUrl" -O "$wrapperJarPath"
|
|
||||||
elif command -v curl > /dev/null; then
|
|
||||||
if [ "$MVNW_VERBOSE" = true ]; then
|
|
||||||
echo "Found curl ... using curl"
|
|
||||||
fi
|
|
||||||
curl -o "$wrapperJarPath" "$jarUrl"
|
|
||||||
else
|
|
||||||
if [ "$MVNW_VERBOSE" = true ]; then
|
|
||||||
echo "Falling back to using Java to download"
|
|
||||||
fi
|
|
||||||
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
|
|
||||||
if [ -e "$javaClass" ]; then
|
|
||||||
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
|
||||||
if [ "$MVNW_VERBOSE" = true ]; then
|
|
||||||
echo " - Compiling MavenWrapperDownloader.java ..."
|
|
||||||
fi
|
|
||||||
# Compiling the Java class
|
|
||||||
("$JAVA_HOME/bin/javac" "$javaClass")
|
|
||||||
fi
|
|
||||||
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
|
||||||
# Running the downloader
|
|
||||||
if [ "$MVNW_VERBOSE" = true ]; then
|
|
||||||
echo " - Running MavenWrapperDownloader.java ..."
|
|
||||||
fi
|
|
||||||
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
##########################################################################################
|
|
||||||
# End of extension
|
|
||||||
##########################################################################################
|
|
||||||
|
|
||||||
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
|
|
||||||
if [ "$MVNW_VERBOSE" = true ]; then
|
|
||||||
echo $MAVEN_PROJECTBASEDIR
|
|
||||||
fi
|
|
||||||
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
|
|
||||||
|
|
||||||
# For Cygwin, switch paths to Windows format before running java
|
|
||||||
if $cygwin; then
|
|
||||||
[ -n "$M2_HOME" ] &&
|
|
||||||
M2_HOME=`cygpath --path --windows "$M2_HOME"`
|
|
||||||
[ -n "$JAVA_HOME" ] &&
|
|
||||||
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
|
|
||||||
[ -n "$CLASSPATH" ] &&
|
|
||||||
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
|
|
||||||
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
|
|
||||||
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
|
|
||||||
fi
|
|
||||||
|
|
||||||
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
|
||||||
|
|
||||||
exec "$JAVACMD" \
|
|
||||||
$MAVEN_OPTS \
|
|
||||||
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
|
||||||
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
|
||||||
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
|
|
||||||
161
mvnw.cmd
vendored
161
mvnw.cmd
vendored
@@ -1,161 +0,0 @@
|
|||||||
@REM ----------------------------------------------------------------------------
|
|
||||||
@REM Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
@REM or more contributor license agreements. See the NOTICE file
|
|
||||||
@REM distributed with this work for additional information
|
|
||||||
@REM regarding copyright ownership. The ASF licenses this file
|
|
||||||
@REM to you under the Apache License, Version 2.0 (the
|
|
||||||
@REM "License"); you may not use this file except in compliance
|
|
||||||
@REM with the License. You may obtain a copy of the License at
|
|
||||||
@REM
|
|
||||||
@REM https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
@REM
|
|
||||||
@REM Unless required by applicable law or agreed to in writing,
|
|
||||||
@REM software distributed under the License is distributed on an
|
|
||||||
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
@REM KIND, either express or implied. See the License for the
|
|
||||||
@REM specific language governing permissions and limitations
|
|
||||||
@REM under the License.
|
|
||||||
@REM ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
@REM ----------------------------------------------------------------------------
|
|
||||||
@REM Maven2 Start Up Batch script
|
|
||||||
@REM
|
|
||||||
@REM Required ENV vars:
|
|
||||||
@REM JAVA_HOME - location of a JDK home dir
|
|
||||||
@REM
|
|
||||||
@REM Optional ENV vars
|
|
||||||
@REM M2_HOME - location of maven2's installed home dir
|
|
||||||
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
|
||||||
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
|
|
||||||
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
|
||||||
@REM e.g. to debug Maven itself, use
|
|
||||||
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
|
||||||
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
|
||||||
@REM ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
|
|
||||||
@echo off
|
|
||||||
@REM set title of command window
|
|
||||||
title %0
|
|
||||||
@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
|
|
||||||
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
|
||||||
|
|
||||||
@REM set %HOME% to equivalent of $HOME
|
|
||||||
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
|
||||||
|
|
||||||
@REM Execute a user defined script before this one
|
|
||||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
|
|
||||||
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
|
|
||||||
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
|
|
||||||
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
|
|
||||||
:skipRcPre
|
|
||||||
|
|
||||||
@setlocal
|
|
||||||
|
|
||||||
set ERROR_CODE=0
|
|
||||||
|
|
||||||
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
|
||||||
@setlocal
|
|
||||||
|
|
||||||
@REM ==== START VALIDATION ====
|
|
||||||
if not "%JAVA_HOME%" == "" goto OkJHome
|
|
||||||
|
|
||||||
echo.
|
|
||||||
echo Error: JAVA_HOME not found in your environment. >&2
|
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
|
||||||
echo location of your Java installation. >&2
|
|
||||||
echo.
|
|
||||||
goto error
|
|
||||||
|
|
||||||
:OkJHome
|
|
||||||
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
|
||||||
|
|
||||||
echo.
|
|
||||||
echo Error: JAVA_HOME is set to an invalid directory. >&2
|
|
||||||
echo JAVA_HOME = "%JAVA_HOME%" >&2
|
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
|
||||||
echo location of your Java installation. >&2
|
|
||||||
echo.
|
|
||||||
goto error
|
|
||||||
|
|
||||||
@REM ==== END VALIDATION ====
|
|
||||||
|
|
||||||
:init
|
|
||||||
|
|
||||||
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
|
||||||
@REM Fallback to current working directory if not found.
|
|
||||||
|
|
||||||
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
|
||||||
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
|
|
||||||
|
|
||||||
set EXEC_DIR=%CD%
|
|
||||||
set WDIR=%EXEC_DIR%
|
|
||||||
:findBaseDir
|
|
||||||
IF EXIST "%WDIR%"\.mvn goto baseDirFound
|
|
||||||
cd ..
|
|
||||||
IF "%WDIR%"=="%CD%" goto baseDirNotFound
|
|
||||||
set WDIR=%CD%
|
|
||||||
goto findBaseDir
|
|
||||||
|
|
||||||
:baseDirFound
|
|
||||||
set MAVEN_PROJECTBASEDIR=%WDIR%
|
|
||||||
cd "%EXEC_DIR%"
|
|
||||||
goto endDetectBaseDir
|
|
||||||
|
|
||||||
:baseDirNotFound
|
|
||||||
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
|
||||||
cd "%EXEC_DIR%"
|
|
||||||
|
|
||||||
:endDetectBaseDir
|
|
||||||
|
|
||||||
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
|
||||||
|
|
||||||
@setlocal EnableExtensions EnableDelayedExpansion
|
|
||||||
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
|
||||||
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
|
||||||
|
|
||||||
:endReadAdditionalConfig
|
|
||||||
|
|
||||||
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
|
||||||
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
|
|
||||||
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
|
||||||
|
|
||||||
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
|
|
||||||
FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO (
|
|
||||||
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
|
|
||||||
)
|
|
||||||
|
|
||||||
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
|
||||||
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
|
|
||||||
if exist %WRAPPER_JAR% (
|
|
||||||
echo Found %WRAPPER_JAR%
|
|
||||||
) else (
|
|
||||||
echo Couldn't find %WRAPPER_JAR%, downloading it ...
|
|
||||||
echo Downloading from: %DOWNLOAD_URL%
|
|
||||||
powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"
|
|
||||||
echo Finished downloading %WRAPPER_JAR%
|
|
||||||
)
|
|
||||||
@REM End of extension
|
|
||||||
|
|
||||||
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
|
|
||||||
if ERRORLEVEL 1 goto error
|
|
||||||
goto end
|
|
||||||
|
|
||||||
:error
|
|
||||||
set ERROR_CODE=1
|
|
||||||
|
|
||||||
:end
|
|
||||||
@endlocal & set ERROR_CODE=%ERROR_CODE%
|
|
||||||
|
|
||||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
|
|
||||||
@REM check for post script, once with legacy .bat ending and once with .cmd ending
|
|
||||||
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
|
|
||||||
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
|
|
||||||
:skipRcPost
|
|
||||||
|
|
||||||
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
|
||||||
if "%MAVEN_BATCH_PAUSE%" == "on" pause
|
|
||||||
|
|
||||||
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
|
|
||||||
|
|
||||||
exit /B %ERROR_CODE%
|
|
||||||
156
pom.xml
156
pom.xml
@@ -1,36 +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 https://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 http://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.DATAMONGO-REACTIVE-SKIP-TAKE-SNAPSHOT</version>
|
<version>1.10.0.RELEASE</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>https://projects.spring.io/spring-data-mongodb</url>
|
<url>http://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.BUILD-SNAPSHOT</version>
|
<version>1.9.0.RELEASE</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.BUILD-SNAPSHOT</springdata.commons>
|
<springdata.commons>1.13.0.RELEASE</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>
|
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<developers>
|
<developers>
|
||||||
@@ -39,7 +39,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>https://pivotal.io</organizationUrl>
|
<organizationUrl>http://www.gopivotal.com</organizationUrl>
|
||||||
<roles>
|
<roles>
|
||||||
<role>Project Lead</role>
|
<role>Project Lead</role>
|
||||||
</roles>
|
</roles>
|
||||||
@@ -50,7 +50,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>https://pivotal.io</organizationUrl>
|
<organizationUrl>http://www.gopivotal.com</organizationUrl>
|
||||||
<roles>
|
<roles>
|
||||||
<role>Developer</role>
|
<role>Developer</role>
|
||||||
</roles>
|
</roles>
|
||||||
@@ -61,7 +61,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>https://pivotal.io</organizationUrl>
|
<organizationUrl>http://www.gopivotal.com</organizationUrl>
|
||||||
<roles>
|
<roles>
|
||||||
<role>Developer</role>
|
<role>Developer</role>
|
||||||
</roles>
|
</roles>
|
||||||
@@ -72,7 +72,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>https://pivotal.io</organizationUrl>
|
<organizationUrl>http://www.gopivotal.com</organizationUrl>
|
||||||
<roles>
|
<roles>
|
||||||
<role>Developer</role>
|
<role>Developer</role>
|
||||||
</roles>
|
</roles>
|
||||||
@@ -83,7 +83,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>https://pivotal.io</organizationUrl>
|
<organizationUrl>http://www.gopivotal.com</organizationUrl>
|
||||||
<roles>
|
<roles>
|
||||||
<role>Developer</role>
|
<role>Developer</role>
|
||||||
</roles>
|
</roles>
|
||||||
@@ -94,18 +94,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>https://pivotal.io</organizationUrl>
|
<organizationUrl>http://www.gopivotal.com</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>https://www.pivotal.io</organizationUrl>
|
|
||||||
<roles>
|
<roles>
|
||||||
<role>Developer</role>
|
<role>Developer</role>
|
||||||
</roles>
|
</roles>
|
||||||
@@ -114,6 +103,105 @@
|
|||||||
</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>
|
||||||
|
|
||||||
|
<id>mongo3</id>
|
||||||
|
<properties>
|
||||||
|
<mongo>3.0.4</mongo>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</profile>
|
||||||
|
|
||||||
|
<profile>
|
||||||
|
|
||||||
|
<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>
|
||||||
<id>release</id>
|
<id>release</id>
|
||||||
@@ -128,15 +216,6 @@
|
|||||||
</build>
|
</build>
|
||||||
</profile>
|
</profile>
|
||||||
|
|
||||||
<profile>
|
|
||||||
<id>benchmarks</id>
|
|
||||||
<modules>
|
|
||||||
<module>spring-data-mongodb</module>
|
|
||||||
<module>spring-data-mongodb-cross-store</module>
|
|
||||||
<module>spring-data-mongodb-distribution</module>
|
|
||||||
<module>spring-data-mongodb-benchmarks</module>
|
|
||||||
</modules>
|
|
||||||
</profile>
|
|
||||||
</profiles>
|
</profiles>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@@ -150,8 +229,8 @@
|
|||||||
|
|
||||||
<repositories>
|
<repositories>
|
||||||
<repository>
|
<repository>
|
||||||
<id>spring-libs-snapshot</id>
|
<id>spring-libs-release</id>
|
||||||
<url>https://repo.spring.io/libs-snapshot</url>
|
<url>https://repo.spring.io/libs-release</url>
|
||||||
</repository>
|
</repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
|
|
||||||
@@ -160,11 +239,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,76 +0,0 @@
|
|||||||
# Benchmarks
|
|
||||||
|
|
||||||
Benchmarks are based on [JMH](http://openjdk.java.net/projects/code-tools/jmh/).
|
|
||||||
|
|
||||||
# Running Benchmarks
|
|
||||||
|
|
||||||
Running benchmarks is disabled by default and can be activated via the `benchmarks` profile.
|
|
||||||
To run the benchmarks with default settings use.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
mvn -P benchmarks clean test
|
|
||||||
```
|
|
||||||
|
|
||||||
A basic report will be printed to the CLI.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Run complete. Total time: 00:00:15
|
|
||||||
|
|
||||||
Benchmark Mode Cnt Score Error Units
|
|
||||||
MappingMongoConverterBenchmark.readObject thrpt 10 1920157,631 ± 64310,809 ops/s
|
|
||||||
MappingMongoConverterBenchmark.writeObject thrpt 10 782732,857 ± 53804,130 ops/s
|
|
||||||
```
|
|
||||||
|
|
||||||
## Running all Benchmarks of a specific class
|
|
||||||
|
|
||||||
To run all Benchmarks of a specific class, just provide its simple class name via the `benchmark` command line argument.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
mvn -P benchmarks clean test -D benchmark=MappingMongoConverterBenchmark
|
|
||||||
```
|
|
||||||
|
|
||||||
## Running a single Benchmark
|
|
||||||
|
|
||||||
To run a single Benchmark provide its containing class simple name followed by `#` and the method name via the `benchmark` command line argument.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
mvn -P benchmarks clean test -D benchmark=MappingMongoConverterBenchmark#readObjectWith2Properties
|
|
||||||
```
|
|
||||||
|
|
||||||
# Saving Benchmark Results
|
|
||||||
|
|
||||||
A detailed benchmark report is stored in JSON format in the `/target/reports/performance` directory.
|
|
||||||
To store the report in a different location use the `benchmarkReportDir` command line argument.
|
|
||||||
|
|
||||||
## MongoDB
|
|
||||||
|
|
||||||
Results can be directly piped to MongoDB by providing a valid [Connection String](https://docs.mongodb.com/manual/reference/connection-string/) via the `publishTo` command line argument.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
mvn -P benchmarks clean test -D publishTo=mongodb://127.0.0.1:27017
|
|
||||||
```
|
|
||||||
|
|
||||||
NOTE: If the uri does not explicitly define a database the default `spring-data-mongodb-benchmarks` is used.
|
|
||||||
|
|
||||||
## HTTP Endpoint
|
|
||||||
|
|
||||||
The benchmark report can also be posted as `application/json` to an HTTP Endpoint by providing a valid URl via the `publishTo` command line argument.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
mvn -P benchmarks clean test -D publishTo=http://127.0.0.1:8080/capture-benchmarks
|
|
||||||
```
|
|
||||||
|
|
||||||
# Customizing Benchmarks
|
|
||||||
|
|
||||||
Following options can be set via command line.
|
|
||||||
|
|
||||||
Option | Default Value
|
|
||||||
--- | ---
|
|
||||||
warmupIterations | 10
|
|
||||||
warmupTime | 1 (seconds)
|
|
||||||
measurementIterations | 10
|
|
||||||
measurementTime | 1 (seconds)
|
|
||||||
forks | 1
|
|
||||||
benchmarkReportDir | /target/reports/performance (always relative to project root dir)
|
|
||||||
benchmark | .* (single benchmark via `classname#benchmark`)
|
|
||||||
publishTo | \[not set\] (mongodb-uri or http-endpoint)
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
<?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>2.2.0.DATAMONGO-REACTIVE-SKIP-TAKE-SNAPSHOT</version>
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<artifactId>spring-data-mongodb-benchmarks</artifactId>
|
|
||||||
<packaging>jar</packaging>
|
|
||||||
|
|
||||||
<name>Spring Data MongoDB - Microbenchmarks</name>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<!-- Skip tests by default; run only if -DskipTests=false is specified or benchmarks profile is activated -->
|
|
||||||
<skipTests>true</skipTests>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>${project.groupId}</groupId>
|
|
||||||
<artifactId>spring-data-mongodb</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>junit</groupId>
|
|
||||||
<artifactId>junit</artifactId>
|
|
||||||
<version>${junit}</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.openjdk.jmh</groupId>
|
|
||||||
<artifactId>jmh-core</artifactId>
|
|
||||||
<version>${jmh.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.openjdk.jmh</groupId>
|
|
||||||
<artifactId>jmh-generator-annprocess</artifactId>
|
|
||||||
<version>${jmh.version}</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<profiles>
|
|
||||||
|
|
||||||
<profile>
|
|
||||||
<id>benchmarks</id>
|
|
||||||
<properties>
|
|
||||||
<skipTests>false</skipTests>
|
|
||||||
</properties>
|
|
||||||
</profile>
|
|
||||||
</profiles>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>pl.project13.maven</groupId>
|
|
||||||
<artifactId>git-commit-id-plugin</artifactId>
|
|
||||||
<version>2.2.2</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<goals>
|
|
||||||
<goal>revision</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>default-jar</id>
|
|
||||||
<phase>never</phase>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-surefire-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<useSystemClassLoader>false</useSystemClassLoader>
|
|
||||||
<testSourceDirectory>${project.build.sourceDirectory}</testSourceDirectory>
|
|
||||||
<testClassesDirectory>${project.build.outputDirectory}</testClassesDirectory>
|
|
||||||
<excludes>
|
|
||||||
<exclude>**/AbstractMicrobenchmark.java</exclude>
|
|
||||||
<exclude>**/*$*.class</exclude>
|
|
||||||
<exclude>**/generated/*.class</exclude>
|
|
||||||
</excludes>
|
|
||||||
<includes>
|
|
||||||
<include>**/*Benchmark*</include>
|
|
||||||
</includes>
|
|
||||||
<systemPropertyVariables>
|
|
||||||
<benchmarkReportDir>${project.build.directory}/reports/performance</benchmarkReportDir>
|
|
||||||
<project.version>${project.version}</project.version>
|
|
||||||
<git.dirty>${git.dirty}</git.dirty>
|
|
||||||
<git.commit.id>${git.commit.id}</git.commit.id>
|
|
||||||
<git.branch>${git.branch}</git.branch>
|
|
||||||
</systemPropertyVariables>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</project>
|
|
||||||
@@ -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
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.data.mongodb.core;
|
|
||||||
|
|
||||||
import org.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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,111 +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
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.data.mongodb.core.convert;
|
|
||||||
|
|
||||||
import static org.springframework.data.mongodb.core.query.Criteria.*;
|
|
||||||
import static org.springframework.data.mongodb.core.query.Query.*;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.bson.types.ObjectId;
|
|
||||||
import org.openjdk.jmh.annotations.Benchmark;
|
|
||||||
import org.openjdk.jmh.annotations.Scope;
|
|
||||||
import org.openjdk.jmh.annotations.Setup;
|
|
||||||
import org.openjdk.jmh.annotations.State;
|
|
||||||
import org.openjdk.jmh.annotations.TearDown;
|
|
||||||
import org.springframework.data.annotation.Id;
|
|
||||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
|
||||||
import org.springframework.data.mongodb.core.mapping.DBRef;
|
|
||||||
import org.springframework.data.mongodb.core.query.Query;
|
|
||||||
import org.springframework.data.mongodb.microbenchmark.AbstractMicrobenchmark;
|
|
||||||
|
|
||||||
import com.mongodb.MongoClient;
|
|
||||||
import com.mongodb.ServerAddress;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Christoph Strobl
|
|
||||||
*/
|
|
||||||
@State(Scope.Benchmark)
|
|
||||||
public class DbRefMappingBenchmark extends AbstractMicrobenchmark {
|
|
||||||
|
|
||||||
private static final String DB_NAME = "dbref-loading-benchmark";
|
|
||||||
|
|
||||||
private MongoClient client;
|
|
||||||
private MongoTemplate template;
|
|
||||||
|
|
||||||
private Query queryObjectWithDBRef;
|
|
||||||
private Query queryObjectWithDBRefList;
|
|
||||||
|
|
||||||
@Setup
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
|
|
||||||
client = new MongoClient(new ServerAddress());
|
|
||||||
template = new MongoTemplate(client, DB_NAME);
|
|
||||||
|
|
||||||
List<RefObject> refObjects = new ArrayList<>();
|
|
||||||
for (int i = 0; i < 1; i++) {
|
|
||||||
RefObject o = new RefObject();
|
|
||||||
template.save(o);
|
|
||||||
refObjects.add(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjectWithDBRef singleDBRef = new ObjectWithDBRef();
|
|
||||||
singleDBRef.ref = refObjects.iterator().next();
|
|
||||||
template.save(singleDBRef);
|
|
||||||
|
|
||||||
ObjectWithDBRef multipleDBRefs = new ObjectWithDBRef();
|
|
||||||
multipleDBRefs.refList = refObjects;
|
|
||||||
template.save(multipleDBRefs);
|
|
||||||
|
|
||||||
queryObjectWithDBRef = query(where("id").is(singleDBRef.id));
|
|
||||||
queryObjectWithDBRefList = query(where("id").is(multipleDBRefs.id));
|
|
||||||
}
|
|
||||||
|
|
||||||
@TearDown
|
|
||||||
public void tearDown() {
|
|
||||||
|
|
||||||
client.dropDatabase(DB_NAME);
|
|
||||||
client.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Benchmark // DATAMONGO-1720
|
|
||||||
public ObjectWithDBRef readSingleDbRef() {
|
|
||||||
return template.findOne(queryObjectWithDBRef, ObjectWithDBRef.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Benchmark // DATAMONGO-1720
|
|
||||||
public ObjectWithDBRef readMultipleDbRefs() {
|
|
||||||
return template.findOne(queryObjectWithDBRefList, ObjectWithDBRef.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Data
|
|
||||||
static class ObjectWithDBRef {
|
|
||||||
|
|
||||||
private @Id ObjectId id;
|
|
||||||
private @DBRef RefObject ref;
|
|
||||||
private @DBRef List<RefObject> refList;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Data
|
|
||||||
static class RefObject {
|
|
||||||
|
|
||||||
private @Id String id;
|
|
||||||
private String someValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,181 +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
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.data.mongodb.core.convert;
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import org.bson.Document;
|
|
||||||
import org.bson.types.ObjectId;
|
|
||||||
import org.openjdk.jmh.annotations.Benchmark;
|
|
||||||
import org.openjdk.jmh.annotations.Scope;
|
|
||||||
import org.openjdk.jmh.annotations.Setup;
|
|
||||||
import org.openjdk.jmh.annotations.State;
|
|
||||||
import org.openjdk.jmh.annotations.TearDown;
|
|
||||||
import org.springframework.data.annotation.Id;
|
|
||||||
import org.springframework.data.geo.Point;
|
|
||||||
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
|
|
||||||
import org.springframework.data.mongodb.core.mapping.Field;
|
|
||||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
|
||||||
import org.springframework.data.mongodb.microbenchmark.AbstractMicrobenchmark;
|
|
||||||
|
|
||||||
import com.mongodb.MongoClient;
|
|
||||||
import com.mongodb.ServerAddress;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Christoph Strobl
|
|
||||||
*/
|
|
||||||
@State(Scope.Benchmark)
|
|
||||||
public class MappingMongoConverterBenchmark extends AbstractMicrobenchmark {
|
|
||||||
|
|
||||||
private static final String DB_NAME = "mapping-mongo-converter-benchmark";
|
|
||||||
|
|
||||||
private MongoClient client;
|
|
||||||
private MongoMappingContext mappingContext;
|
|
||||||
private MappingMongoConverter converter;
|
|
||||||
private Document documentWith2Properties, documentWith2PropertiesAnd1Nested;
|
|
||||||
private Customer objectWith2PropertiesAnd1Nested;
|
|
||||||
|
|
||||||
private Document documentWithFlatAndComplexPropertiesPlusListAndMap;
|
|
||||||
private SlightlyMoreComplexObject objectWithFlatAndComplexPropertiesPlusListAndMap;
|
|
||||||
|
|
||||||
@Setup
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
|
|
||||||
client = new MongoClient(new ServerAddress());
|
|
||||||
|
|
||||||
this.mappingContext = new MongoMappingContext();
|
|
||||||
this.mappingContext.setInitialEntitySet(Collections.singleton(Customer.class));
|
|
||||||
this.mappingContext.afterPropertiesSet();
|
|
||||||
|
|
||||||
DbRefResolver dbRefResolver = new DefaultDbRefResolver(new SimpleMongoDbFactory(client, DB_NAME));
|
|
||||||
|
|
||||||
this.converter = new MappingMongoConverter(dbRefResolver, mappingContext);
|
|
||||||
this.converter.setCustomConversions(new MongoCustomConversions(Collections.emptyList()));
|
|
||||||
this.converter.afterPropertiesSet();
|
|
||||||
|
|
||||||
// just a flat document
|
|
||||||
this.documentWith2Properties = new Document("firstname", "Dave").append("lastname", "Matthews");
|
|
||||||
|
|
||||||
// document with a nested one
|
|
||||||
Document address = new Document("zipCode", "ABCDE").append("city", "Some Place");
|
|
||||||
this.documentWith2PropertiesAnd1Nested = new Document("firstname", "Dave").//
|
|
||||||
append("lastname", "Matthews").//
|
|
||||||
append("address", address);
|
|
||||||
|
|
||||||
// object equivalent of documentWith2PropertiesAnd1Nested
|
|
||||||
this.objectWith2PropertiesAnd1Nested = new Customer("Dave", "Matthews", new Address("zipCode", "City"));
|
|
||||||
|
|
||||||
// a bit more challenging object with list & map conversion.
|
|
||||||
objectWithFlatAndComplexPropertiesPlusListAndMap = new SlightlyMoreComplexObject();
|
|
||||||
objectWithFlatAndComplexPropertiesPlusListAndMap.id = UUID.randomUUID().toString();
|
|
||||||
objectWithFlatAndComplexPropertiesPlusListAndMap.addressList = Arrays.asList(new Address("zip-1", "city-1"),
|
|
||||||
new Address("zip-2", "city-2"));
|
|
||||||
objectWithFlatAndComplexPropertiesPlusListAndMap.customer = objectWith2PropertiesAnd1Nested;
|
|
||||||
objectWithFlatAndComplexPropertiesPlusListAndMap.customerMap = new LinkedHashMap<>();
|
|
||||||
objectWithFlatAndComplexPropertiesPlusListAndMap.customerMap.put("dave", objectWith2PropertiesAnd1Nested);
|
|
||||||
objectWithFlatAndComplexPropertiesPlusListAndMap.customerMap.put("deborah",
|
|
||||||
new Customer("Deborah Anne", "Dyer", new Address("?", "london")));
|
|
||||||
objectWithFlatAndComplexPropertiesPlusListAndMap.customerMap.put("eddie",
|
|
||||||
new Customer("Eddie", "Vedder", new Address("??", "Seattle")));
|
|
||||||
objectWithFlatAndComplexPropertiesPlusListAndMap.intOne = Integer.MIN_VALUE;
|
|
||||||
objectWithFlatAndComplexPropertiesPlusListAndMap.intTwo = Integer.MAX_VALUE;
|
|
||||||
objectWithFlatAndComplexPropertiesPlusListAndMap.location = new Point(-33.865143, 151.209900);
|
|
||||||
objectWithFlatAndComplexPropertiesPlusListAndMap.renamedField = "supercalifragilisticexpialidocious";
|
|
||||||
objectWithFlatAndComplexPropertiesPlusListAndMap.stringOne = "¯\\_(ツ)_/¯";
|
|
||||||
objectWithFlatAndComplexPropertiesPlusListAndMap.stringTwo = " (╯°□°)╯︵ ┻━┻";
|
|
||||||
|
|
||||||
// JSON equivalent of objectWithFlatAndComplexPropertiesPlusListAndMap
|
|
||||||
documentWithFlatAndComplexPropertiesPlusListAndMap = Document.parse(
|
|
||||||
"{ \"_id\" : \"517f6aee-e9e0-44f0-88ed-f3694a019f27\", \"intOne\" : -2147483648, \"intTwo\" : 2147483647, \"stringOne\" : \"¯\\\\_(ツ)_/¯\", \"stringTwo\" : \" (╯°□°)╯︵ ┻━┻\", \"explicit-field-name\" : \"supercalifragilisticexpialidocious\", \"location\" : { \"x\" : -33.865143, \"y\" : 151.2099 }, \"objectWith2PropertiesAnd1Nested\" : { \"firstname\" : \"Dave\", \"lastname\" : \"Matthews\", \"address\" : { \"zipCode\" : \"zipCode\", \"city\" : \"City\" } }, \"addressList\" : [{ \"zipCode\" : \"zip-1\", \"city\" : \"city-1\" }, { \"zipCode\" : \"zip-2\", \"city\" : \"city-2\" }], \"customerMap\" : { \"dave\" : { \"firstname\" : \"Dave\", \"lastname\" : \"Matthews\", \"address\" : { \"zipCode\" : \"zipCode\", \"city\" : \"City\" } }, \"deborah\" : { \"firstname\" : \"Deborah Anne\", \"lastname\" : \"Dyer\", \"address\" : { \"zipCode\" : \"?\", \"city\" : \"london\" } }, \"eddie\" : { \"firstname\" : \"Eddie\", \"lastname\" : \"Vedder\", \"address\" : { \"zipCode\" : \"??\", \"city\" : \"Seattle\" } } }, \"_class\" : \"org.springframework.data.mongodb.core.convert.MappingMongoConverterBenchmark$SlightlyMoreComplexObject\" }");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@TearDown
|
|
||||||
public void tearDown() {
|
|
||||||
|
|
||||||
client.dropDatabase(DB_NAME);
|
|
||||||
client.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Benchmark // DATAMONGO-1720
|
|
||||||
public Customer readObjectWith2Properties() {
|
|
||||||
return converter.read(Customer.class, documentWith2Properties);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Benchmark // DATAMONGO-1720
|
|
||||||
public Customer readObjectWith2PropertiesAnd1NestedObject() {
|
|
||||||
return converter.read(Customer.class, documentWith2PropertiesAnd1Nested);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Benchmark // DATAMONGO-1720
|
|
||||||
public Document writeObjectWith2PropertiesAnd1NestedObject() {
|
|
||||||
|
|
||||||
Document sink = new Document();
|
|
||||||
converter.write(objectWith2PropertiesAnd1Nested, sink);
|
|
||||||
return sink;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Benchmark // DATAMONGO-1720
|
|
||||||
public Object readObjectWithListAndMapsOfComplexType() {
|
|
||||||
return converter.read(SlightlyMoreComplexObject.class, documentWithFlatAndComplexPropertiesPlusListAndMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Benchmark // DATAMONGO-1720
|
|
||||||
public Object writeObjectWithListAndMapsOfComplexType() {
|
|
||||||
|
|
||||||
Document sink = new Document();
|
|
||||||
converter.write(objectWithFlatAndComplexPropertiesPlusListAndMap, sink);
|
|
||||||
return sink;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
static class Customer {
|
|
||||||
|
|
||||||
private @Id ObjectId id;
|
|
||||||
private final String firstname, lastname;
|
|
||||||
private final Address address;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@AllArgsConstructor
|
|
||||||
static class Address {
|
|
||||||
private String zipCode, city;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Data
|
|
||||||
static class SlightlyMoreComplexObject {
|
|
||||||
|
|
||||||
@Id String id;
|
|
||||||
int intOne, intTwo;
|
|
||||||
String stringOne, stringTwo;
|
|
||||||
@Field("explicit-field-name") String renamedField;
|
|
||||||
Point location;
|
|
||||||
Customer customer;
|
|
||||||
List<Address> addressList;
|
|
||||||
Map<String, Customer> customerMap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,328 +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
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.data.mongodb.microbenchmark;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.openjdk.jmh.annotations.Fork;
|
|
||||||
import org.openjdk.jmh.annotations.Measurement;
|
|
||||||
import org.openjdk.jmh.annotations.Scope;
|
|
||||||
import org.openjdk.jmh.annotations.State;
|
|
||||||
import org.openjdk.jmh.annotations.Warmup;
|
|
||||||
import org.openjdk.jmh.results.RunResult;
|
|
||||||
import org.openjdk.jmh.results.format.ResultFormatType;
|
|
||||||
import org.openjdk.jmh.runner.Runner;
|
|
||||||
import org.openjdk.jmh.runner.options.ChainedOptionsBuilder;
|
|
||||||
import org.openjdk.jmh.runner.options.OptionsBuilder;
|
|
||||||
import org.openjdk.jmh.runner.options.TimeValue;
|
|
||||||
import org.springframework.core.env.StandardEnvironment;
|
|
||||||
import org.springframework.util.CollectionUtils;
|
|
||||||
import org.springframework.util.ResourceUtils;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Christoph Strobl
|
|
||||||
*/
|
|
||||||
@Warmup(iterations = AbstractMicrobenchmark.WARMUP_ITERATIONS)
|
|
||||||
@Measurement(iterations = AbstractMicrobenchmark.MEASUREMENT_ITERATIONS)
|
|
||||||
@Fork(AbstractMicrobenchmark.FORKS)
|
|
||||||
@State(Scope.Thread)
|
|
||||||
public class AbstractMicrobenchmark {
|
|
||||||
|
|
||||||
static final int WARMUP_ITERATIONS = 5;
|
|
||||||
static final int MEASUREMENT_ITERATIONS = 10;
|
|
||||||
static final int FORKS = 1;
|
|
||||||
static final String[] JVM_ARGS = { "-server", "-XX:+HeapDumpOnOutOfMemoryError", "-Xms1024m", "-Xmx1024m",
|
|
||||||
"-XX:MaxDirectMemorySize=1024m" };
|
|
||||||
|
|
||||||
private final StandardEnvironment environment = new StandardEnvironment();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run matching {@link org.openjdk.jmh.annotations.Benchmark} methods with options collected from
|
|
||||||
* {@link org.springframework.core.env.Environment}.
|
|
||||||
*
|
|
||||||
* @throws Exception
|
|
||||||
* @see #options(String)
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void run() throws Exception {
|
|
||||||
|
|
||||||
String includes = includes();
|
|
||||||
|
|
||||||
if (!includes.contains(org.springframework.util.ClassUtils.getShortName(getClass()))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
publishResults(new Runner(options(includes).build()).run());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the regex for all benchmarks to be included in the run. By default every benchmark within classes matching the
|
|
||||||
* current ones short name. <br />
|
|
||||||
* The {@literal benchmark} command line argument allows overriding the defaults using {@code #} as class / method
|
|
||||||
* name separator.
|
|
||||||
*
|
|
||||||
* @return never {@literal null}.
|
|
||||||
* @see org.springframework.util.ClassUtils#getShortName(Class)
|
|
||||||
*/
|
|
||||||
protected String includes() {
|
|
||||||
|
|
||||||
String tests = environment.getProperty("benchmark", String.class);
|
|
||||||
|
|
||||||
if (!StringUtils.hasText(tests)) {
|
|
||||||
return ".*" + org.springframework.util.ClassUtils.getShortName(getClass()) + ".*";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tests.contains("#")) {
|
|
||||||
return ".*" + tests + ".*";
|
|
||||||
}
|
|
||||||
|
|
||||||
String[] args = tests.split("#");
|
|
||||||
return ".*" + args[0] + "." + args[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Collect all options for the {@link Runner}.
|
|
||||||
*
|
|
||||||
* @param includes regex for matching benchmarks to be included in the run.
|
|
||||||
* @return never {@literal null}.
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
protected ChainedOptionsBuilder options(String includes) throws Exception {
|
|
||||||
|
|
||||||
ChainedOptionsBuilder optionsBuilder = new OptionsBuilder().include(includes).jvmArgs(jvmArgs());
|
|
||||||
|
|
||||||
optionsBuilder = warmup(optionsBuilder);
|
|
||||||
optionsBuilder = measure(optionsBuilder);
|
|
||||||
optionsBuilder = forks(optionsBuilder);
|
|
||||||
optionsBuilder = report(optionsBuilder);
|
|
||||||
|
|
||||||
return optionsBuilder;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* JVM args to apply to {@link Runner} via its {@link org.openjdk.jmh.runner.options.Options}.
|
|
||||||
*
|
|
||||||
* @return {@link #JVM_ARGS} by default.
|
|
||||||
*/
|
|
||||||
protected String[] jvmArgs() {
|
|
||||||
|
|
||||||
String[] args = new String[JVM_ARGS.length];
|
|
||||||
System.arraycopy(JVM_ARGS, 0, args, 0, JVM_ARGS.length);
|
|
||||||
return args;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read {@code warmupIterations} property from {@link org.springframework.core.env.Environment}.
|
|
||||||
*
|
|
||||||
* @return -1 if not set.
|
|
||||||
*/
|
|
||||||
protected int getWarmupIterations() {
|
|
||||||
return environment.getProperty("warmupIterations", Integer.class, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read {@code measurementIterations} property from {@link org.springframework.core.env.Environment}.
|
|
||||||
*
|
|
||||||
* @return -1 if not set.
|
|
||||||
*/
|
|
||||||
protected int getMeasurementIterations() {
|
|
||||||
return environment.getProperty("measurementIterations", Integer.class, -1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read {@code forks} property from {@link org.springframework.core.env.Environment}.
|
|
||||||
*
|
|
||||||
* @return -1 if not set.
|
|
||||||
*/
|
|
||||||
protected int getForksCount() {
|
|
||||||
return environment.getProperty("forks", Integer.class, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read {@code benchmarkReportDir} property from {@link org.springframework.core.env.Environment}.
|
|
||||||
*
|
|
||||||
* @return {@literal null} if not set.
|
|
||||||
*/
|
|
||||||
protected String getReportDirectory() {
|
|
||||||
return environment.getProperty("benchmarkReportDir");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read {@code measurementTime} property from {@link org.springframework.core.env.Environment}.
|
|
||||||
*
|
|
||||||
* @return -1 if not set.
|
|
||||||
*/
|
|
||||||
protected long getMeasurementTime() {
|
|
||||||
return environment.getProperty("measurementTime", Long.class, -1L);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read {@code warmupTime} property from {@link org.springframework.core.env.Environment}.
|
|
||||||
*
|
|
||||||
* @return -1 if not set.
|
|
||||||
*/
|
|
||||||
protected long getWarmupTime() {
|
|
||||||
return environment.getProperty("warmupTime", Long.class, -1L);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@code project.version_yyyy-MM-dd_ClassName.json} eg.
|
|
||||||
* {@literal 1.11.0.BUILD-SNAPSHOT_2017-03-07_MappingMongoConverterBenchmark.json}
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
protected String reportFilename() {
|
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
|
|
||||||
if (environment.containsProperty("project.version")) {
|
|
||||||
|
|
||||||
sb.append(environment.getProperty("project.version"));
|
|
||||||
sb.append("_");
|
|
||||||
}
|
|
||||||
|
|
||||||
sb.append(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
|
|
||||||
sb.append("_");
|
|
||||||
sb.append(org.springframework.util.ClassUtils.getShortName(getClass()));
|
|
||||||
sb.append(".json");
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply measurement options to {@link ChainedOptionsBuilder}.
|
|
||||||
*
|
|
||||||
* @param optionsBuilder must not be {@literal null}.
|
|
||||||
* @return {@link ChainedOptionsBuilder} with options applied.
|
|
||||||
* @see #getMeasurementIterations()
|
|
||||||
* @see #getMeasurementTime()
|
|
||||||
*/
|
|
||||||
private ChainedOptionsBuilder measure(ChainedOptionsBuilder optionsBuilder) {
|
|
||||||
|
|
||||||
int measurementIterations = getMeasurementIterations();
|
|
||||||
long measurementTime = getMeasurementTime();
|
|
||||||
|
|
||||||
if (measurementIterations > 0) {
|
|
||||||
optionsBuilder = optionsBuilder.measurementIterations(measurementIterations);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (measurementTime > 0) {
|
|
||||||
optionsBuilder = optionsBuilder.measurementTime(TimeValue.seconds(measurementTime));
|
|
||||||
}
|
|
||||||
|
|
||||||
return optionsBuilder;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply warmup options to {@link ChainedOptionsBuilder}.
|
|
||||||
*
|
|
||||||
* @param optionsBuilder must not be {@literal null}.
|
|
||||||
* @return {@link ChainedOptionsBuilder} with options applied.
|
|
||||||
* @see #getWarmupIterations()
|
|
||||||
* @see #getWarmupTime()
|
|
||||||
*/
|
|
||||||
private ChainedOptionsBuilder warmup(ChainedOptionsBuilder optionsBuilder) {
|
|
||||||
|
|
||||||
int warmupIterations = getWarmupIterations();
|
|
||||||
long warmupTime = getWarmupTime();
|
|
||||||
|
|
||||||
if (warmupIterations > 0) {
|
|
||||||
optionsBuilder = optionsBuilder.warmupIterations(warmupIterations);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (warmupTime > 0) {
|
|
||||||
optionsBuilder = optionsBuilder.warmupTime(TimeValue.seconds(warmupTime));
|
|
||||||
}
|
|
||||||
|
|
||||||
return optionsBuilder;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply forks option to {@link ChainedOptionsBuilder}.
|
|
||||||
*
|
|
||||||
* @param optionsBuilder must not be {@literal null}.
|
|
||||||
* @return {@link ChainedOptionsBuilder} with options applied.
|
|
||||||
* @see #getForksCount()
|
|
||||||
*/
|
|
||||||
private ChainedOptionsBuilder forks(ChainedOptionsBuilder optionsBuilder) {
|
|
||||||
|
|
||||||
int forks = getForksCount();
|
|
||||||
|
|
||||||
if (forks <= 0) {
|
|
||||||
return optionsBuilder;
|
|
||||||
}
|
|
||||||
|
|
||||||
return optionsBuilder.forks(forks);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply report option to {@link ChainedOptionsBuilder}.
|
|
||||||
*
|
|
||||||
* @param optionsBuilder must not be {@literal null}.
|
|
||||||
* @return {@link ChainedOptionsBuilder} with options applied.
|
|
||||||
* @throws IOException if report file cannot be created.
|
|
||||||
* @see #getReportDirectory()
|
|
||||||
*/
|
|
||||||
private ChainedOptionsBuilder report(ChainedOptionsBuilder optionsBuilder) throws IOException {
|
|
||||||
|
|
||||||
String reportDir = getReportDirectory();
|
|
||||||
|
|
||||||
if (!StringUtils.hasText(reportDir)) {
|
|
||||||
return optionsBuilder;
|
|
||||||
}
|
|
||||||
|
|
||||||
String reportFilePath = reportDir + (reportDir.endsWith(File.separator) ? "" : File.separator) + reportFilename();
|
|
||||||
File file = ResourceUtils.getFile(reportFilePath);
|
|
||||||
|
|
||||||
if (file.exists()) {
|
|
||||||
file.delete();
|
|
||||||
} else {
|
|
||||||
|
|
||||||
file.getParentFile().mkdirs();
|
|
||||||
file.createNewFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
optionsBuilder.resultFormat(ResultFormatType.JSON);
|
|
||||||
optionsBuilder.result(reportFilePath);
|
|
||||||
|
|
||||||
return optionsBuilder;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Publish results to an external system.
|
|
||||||
*
|
|
||||||
* @param results must not be {@literal null}.
|
|
||||||
*/
|
|
||||||
private void publishResults(Collection<RunResult> results) {
|
|
||||||
|
|
||||||
if (CollectionUtils.isEmpty(results) || !environment.containsProperty("publishTo")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String uri = environment.getProperty("publishTo");
|
|
||||||
try {
|
|
||||||
ResultsWriter.forUri(uri).write(results);
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.err.println(String.format("Cannot save benchmark results to '%s'. Error was %s.", uri, e));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,81 +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
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.data.mongodb.microbenchmark;
|
|
||||||
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.URLConnection;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
import org.openjdk.jmh.results.RunResult;
|
|
||||||
import org.springframework.core.env.StandardEnvironment;
|
|
||||||
import org.springframework.util.CollectionUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link ResultsWriter} implementation of {@link URLConnection}.
|
|
||||||
*
|
|
||||||
* @since 2.0
|
|
||||||
*/
|
|
||||||
class HttpResultsWriter implements ResultsWriter {
|
|
||||||
|
|
||||||
private final String url;
|
|
||||||
|
|
||||||
HttpResultsWriter(String url) {
|
|
||||||
this.url = url;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@SneakyThrows
|
|
||||||
public void write(Collection<RunResult> results) {
|
|
||||||
|
|
||||||
if (CollectionUtils.isEmpty(results)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
StandardEnvironment env = new StandardEnvironment();
|
|
||||||
|
|
||||||
String projectVersion = env.getProperty("project.version", "unknown");
|
|
||||||
String gitBranch = env.getProperty("git.branch", "unknown");
|
|
||||||
String gitDirty = env.getProperty("git.dirty", "no");
|
|
||||||
String gitCommitId = env.getProperty("git.commit.id", "unknown");
|
|
||||||
|
|
||||||
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
|
|
||||||
connection.setConnectTimeout((int) Duration.ofSeconds(1).toMillis());
|
|
||||||
connection.setReadTimeout((int) Duration.ofSeconds(1).toMillis());
|
|
||||||
connection.setDoOutput(true);
|
|
||||||
connection.setRequestMethod("POST");
|
|
||||||
|
|
||||||
connection.setRequestProperty("Content-Type", "application/json");
|
|
||||||
connection.addRequestProperty("X-Project-Version", projectVersion);
|
|
||||||
connection.addRequestProperty("X-Git-Branch", gitBranch);
|
|
||||||
connection.addRequestProperty("X-Git-Dirty", gitDirty);
|
|
||||||
connection.addRequestProperty("X-Git-Commit-Id", gitCommitId);
|
|
||||||
|
|
||||||
try (OutputStream output = connection.getOutputStream()) {
|
|
||||||
output.write(ResultsWriter.jsonifyResults(results).getBytes(StandardCharsets.UTF_8));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (connection.getResponseCode() >= 400) {
|
|
||||||
throw new IllegalStateException(
|
|
||||||
String.format("Status %d %s", connection.getResponseCode(), connection.getResponseMessage()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,131 +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
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.data.mongodb.microbenchmark;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.bson.Document;
|
|
||||||
import org.openjdk.jmh.results.RunResult;
|
|
||||||
import org.springframework.core.env.StandardEnvironment;
|
|
||||||
import org.springframework.util.ObjectUtils;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
|
||||||
import com.mongodb.MongoClient;
|
|
||||||
import com.mongodb.MongoClientURI;
|
|
||||||
import com.mongodb.client.MongoDatabase;
|
|
||||||
import com.mongodb.util.JSON;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MongoDB specific {@link ResultsWriter} implementation.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 2.0
|
|
||||||
*/
|
|
||||||
class MongoResultsWriter implements ResultsWriter {
|
|
||||||
|
|
||||||
private final String uri;
|
|
||||||
|
|
||||||
MongoResultsWriter(String uri) {
|
|
||||||
this.uri = uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(Collection<RunResult> results) {
|
|
||||||
|
|
||||||
Date now = new Date();
|
|
||||||
StandardEnvironment env = new StandardEnvironment();
|
|
||||||
|
|
||||||
String projectVersion = env.getProperty("project.version", "unknown");
|
|
||||||
String gitBranch = env.getProperty("git.branch", "unknown");
|
|
||||||
String gitDirty = env.getProperty("git.dirty", "no");
|
|
||||||
String gitCommitId = env.getProperty("git.commit.id", "unknown");
|
|
||||||
|
|
||||||
MongoClientURI uri = new MongoClientURI(this.uri);
|
|
||||||
MongoClient client = new MongoClient(uri);
|
|
||||||
|
|
||||||
String dbName = StringUtils.hasText(uri.getDatabase()) ? uri.getDatabase() : "spring-data-mongodb-benchmarks";
|
|
||||||
MongoDatabase db = client.getDatabase(dbName);
|
|
||||||
|
|
||||||
for (BasicDBObject dbo : (List<BasicDBObject>) JSON.parse(ResultsWriter.jsonifyResults(results))) {
|
|
||||||
|
|
||||||
String collectionName = extractClass(dbo.get("benchmark").toString());
|
|
||||||
|
|
||||||
Document sink = new Document();
|
|
||||||
sink.append("_version", projectVersion);
|
|
||||||
sink.append("_branch", gitBranch);
|
|
||||||
sink.append("_commit", gitCommitId);
|
|
||||||
sink.append("_dirty", gitDirty);
|
|
||||||
sink.append("_method", extractBenchmarkName(dbo.get("benchmark").toString()));
|
|
||||||
sink.append("_date", now);
|
|
||||||
sink.append("_snapshot", projectVersion.toLowerCase().contains("snapshot"));
|
|
||||||
|
|
||||||
sink.putAll(dbo);
|
|
||||||
|
|
||||||
db.getCollection(collectionName).insertOne(fixDocumentKeys(sink));
|
|
||||||
}
|
|
||||||
|
|
||||||
client.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Replace {@code .} by {@code ,}.
|
|
||||||
*
|
|
||||||
* @param doc
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private Document fixDocumentKeys(Document doc) {
|
|
||||||
|
|
||||||
Document sanitized = new Document();
|
|
||||||
|
|
||||||
for (Object key : doc.keySet()) {
|
|
||||||
|
|
||||||
Object value = doc.get(key);
|
|
||||||
if (value instanceof Document) {
|
|
||||||
value = fixDocumentKeys((Document) value);
|
|
||||||
} else if (value instanceof BasicDBObject) {
|
|
||||||
value = fixDocumentKeys(new Document((BasicDBObject) value));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key instanceof String) {
|
|
||||||
|
|
||||||
String newKey = (String) key;
|
|
||||||
if (newKey.contains(".")) {
|
|
||||||
newKey = newKey.replace('.', ',');
|
|
||||||
}
|
|
||||||
|
|
||||||
sanitized.put(newKey, value);
|
|
||||||
} else {
|
|
||||||
sanitized.put(ObjectUtils.nullSafeToString(key).replace('.', ','), value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return sanitized;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String extractClass(String source) {
|
|
||||||
|
|
||||||
String tmp = source.substring(0, source.lastIndexOf('.'));
|
|
||||||
return tmp.substring(tmp.lastIndexOf(".") + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String extractBenchmarkName(String source) {
|
|
||||||
return source.substring(source.lastIndexOf(".") + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,67 +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
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.data.mongodb.microbenchmark;
|
|
||||||
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.PrintStream;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
import org.openjdk.jmh.results.RunResult;
|
|
||||||
import org.openjdk.jmh.results.format.ResultFormatFactory;
|
|
||||||
import org.openjdk.jmh.results.format.ResultFormatType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 2.0
|
|
||||||
*/
|
|
||||||
interface ResultsWriter {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write the {@link RunResult}s.
|
|
||||||
*
|
|
||||||
* @param results can be {@literal null}.
|
|
||||||
*/
|
|
||||||
void write(Collection<RunResult> results);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the uri specific {@link ResultsWriter}.
|
|
||||||
*
|
|
||||||
* @param uri must not be {@literal null}.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
static ResultsWriter forUri(String uri) {
|
|
||||||
return uri.startsWith("mongodb:") ? new MongoResultsWriter(uri) : new HttpResultsWriter(uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert {@link RunResult}s to JMH Json representation.
|
|
||||||
*
|
|
||||||
* @param results
|
|
||||||
* @return json string representation of results.
|
|
||||||
* @see org.openjdk.jmh.results.format.JSONResultFormat
|
|
||||||
*/
|
|
||||||
@SneakyThrows
|
|
||||||
static String jsonifyResults(Collection<RunResult> results) {
|
|
||||||
|
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
||||||
ResultFormatFactory.getInstance(ResultFormatType.JSON, new PrintStream(baos, true, "UTF-8")).writeOut(results);
|
|
||||||
|
|
||||||
return new String(baos.toByteArray(), StandardCharsets.UTF_8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<configuration>
|
|
||||||
|
|
||||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
|
||||||
<encoder>
|
|
||||||
<pattern>%d %5p %40.40c:%4L - %m%n</pattern>
|
|
||||||
</encoder>
|
|
||||||
</appender>
|
|
||||||
|
|
||||||
<root level="error">
|
|
||||||
<appender-ref ref="console" />
|
|
||||||
</root>
|
|
||||||
|
|
||||||
</configuration>
|
|
||||||
@@ -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 https://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 http://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.DATAMONGO-REACTIVE-SKIP-TAKE-SNAPSHOT</version>
|
<version>1.10.0.RELEASE</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
@@ -14,10 +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>
|
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@@ -50,14 +48,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.DATAMONGO-REACTIVE-SKIP-TAKE-SNAPSHOT</version>
|
<version>1.10.0.RELEASE</version>
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- reactive -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.projectreactor</groupId>
|
|
||||||
<artifactId>reactor-core</artifactId>
|
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -96,7 +87,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>
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2019 the original author or authors.
|
* Copyright 2011 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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 {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,214 +1,197 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2019 the original author or authors.
|
* Copyright 2011-2016 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* 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.crossstore;
|
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;
|
import org.springframework.dao.DataAccessResourceFailureException;
|
||||||
import org.springframework.dao.DataAccessResourceFailureException;
|
import org.springframework.dao.DataIntegrityViolationException;
|
||||||
import org.springframework.dao.DataIntegrityViolationException;
|
import org.springframework.data.crossstore.ChangeSet;
|
||||||
import org.springframework.data.crossstore.ChangeSet;
|
import org.springframework.data.crossstore.ChangeSetBacked;
|
||||||
import org.springframework.data.crossstore.ChangeSetBacked;
|
import org.springframework.data.crossstore.ChangeSetPersister;
|
||||||
import org.springframework.data.crossstore.ChangeSetPersister;
|
import org.springframework.data.mongodb.core.CollectionCallback;
|
||||||
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.MongoException;
|
import com.mongodb.DBCollection;
|
||||||
import com.mongodb.client.MongoCollection;
|
import com.mongodb.DBObject;
|
||||||
import com.mongodb.client.model.Filters;
|
import com.mongodb.MongoException;
|
||||||
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.
|
public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
||||||
*/
|
|
||||||
@Deprecated
|
private static final String ENTITY_CLASS = "_entity_class";
|
||||||
public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
private static final String ENTITY_ID = "_entity_id";
|
||||||
|
private static final String ENTITY_FIELD_NAME = "_entity_field_name";
|
||||||
private static final String ENTITY_CLASS = "_entity_class";
|
private static final String ENTITY_FIELD_CLASS = "_entity_field_class";
|
||||||
private static final String ENTITY_ID = "_entity_id";
|
|
||||||
private static final String ENTITY_FIELD_NAME = "_entity_field_name";
|
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||||
private static final String ENTITY_FIELD_CLASS = "_entity_field_class";
|
|
||||||
|
private MongoTemplate mongoTemplate;
|
||||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
private EntityManagerFactory entityManagerFactory;
|
||||||
|
|
||||||
private MongoTemplate mongoTemplate;
|
public void setMongoTemplate(MongoTemplate mongoTemplate) {
|
||||||
private EntityManagerFactory entityManagerFactory;
|
this.mongoTemplate = mongoTemplate;
|
||||||
|
}
|
||||||
public void setMongoTemplate(MongoTemplate mongoTemplate) {
|
|
||||||
this.mongoTemplate = mongoTemplate;
|
public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) {
|
||||||
}
|
this.entityManagerFactory = entityManagerFactory;
|
||||||
|
}
|
||||||
public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) {
|
|
||||||
this.entityManagerFactory = entityManagerFactory;
|
/*
|
||||||
}
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.crossstore.ChangeSetPersister#getPersistentState(java.lang.Class, java.lang.Object, org.springframework.data.crossstore.ChangeSet)
|
||||||
/*
|
*/
|
||||||
* (non-Javadoc)
|
public void getPersistentState(Class<? extends ChangeSetBacked> entityClass, Object id, final ChangeSet changeSet)
|
||||||
* @see org.springframework.data.crossstore.ChangeSetPersister#getPersistentState(java.lang.Class, java.lang.Object, org.springframework.data.crossstore.ChangeSet)
|
throws DataAccessException, NotFoundException {
|
||||||
*/
|
|
||||||
public void getPersistentState(Class<? extends ChangeSetBacked> entityClass, Object id, final ChangeSet changeSet)
|
if (id == null) {
|
||||||
throws DataAccessException, NotFoundException {
|
log.debug("Unable to load MongoDB data for null id");
|
||||||
|
return;
|
||||||
if (id == null) {
|
}
|
||||||
log.debug("Unable to load MongoDB data for null id");
|
|
||||||
return;
|
String collName = getCollectionNameForEntity(entityClass);
|
||||||
}
|
|
||||||
|
final DBObject dbk = new BasicDBObject();
|
||||||
String collName = getCollectionNameForEntity(entityClass);
|
dbk.put(ENTITY_ID, id);
|
||||||
|
dbk.put(ENTITY_CLASS, entityClass.getName());
|
||||||
final Document dbk = new Document();
|
if (log.isDebugEnabled()) {
|
||||||
dbk.put(ENTITY_ID, id);
|
log.debug("Loading MongoDB data for {}", dbk);
|
||||||
dbk.put(ENTITY_CLASS, entityClass.getName());
|
}
|
||||||
if (log.isDebugEnabled()) {
|
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
|
||||||
log.debug("Loading MongoDB data for {}", dbk);
|
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||||
}
|
for (DBObject dbo : collection.find(dbk)) {
|
||||||
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
|
String key = (String) dbo.get(ENTITY_FIELD_NAME);
|
||||||
public Object doInCollection(MongoCollection<Document> collection) throws MongoException, DataAccessException {
|
if (log.isDebugEnabled()) {
|
||||||
for (Document dbo : collection.find(dbk)) {
|
log.debug("Processing key: {}", key);
|
||||||
String key = (String) dbo.get(ENTITY_FIELD_NAME);
|
}
|
||||||
if (log.isDebugEnabled()) {
|
if (!changeSet.getValues().containsKey(key)) {
|
||||||
log.debug("Processing key: {}", key);
|
String className = (String) dbo.get(ENTITY_FIELD_CLASS);
|
||||||
}
|
if (className == null) {
|
||||||
if (!changeSet.getValues().containsKey(key)) {
|
throw new DataIntegrityViolationException(
|
||||||
String className = (String) dbo.get(ENTITY_FIELD_CLASS);
|
"Unble to convert property " + key + ": Invalid metadata, " + ENTITY_FIELD_CLASS + " not available");
|
||||||
if (className == null) {
|
}
|
||||||
throw new DataIntegrityViolationException(
|
Class<?> clazz = ClassUtils.resolveClassName(className, ClassUtils.getDefaultClassLoader());
|
||||||
"Unble to convert property " + key + ": Invalid metadata, " + ENTITY_FIELD_CLASS + " not available");
|
Object value = mongoTemplate.getConverter().read(clazz, dbo);
|
||||||
}
|
if (log.isDebugEnabled()) {
|
||||||
Class<?> clazz = ClassUtils.resolveClassName(className, ClassUtils.getDefaultClassLoader());
|
log.debug("Adding to ChangeSet: {}", key);
|
||||||
Object value = mongoTemplate.getConverter().read(clazz, dbo);
|
}
|
||||||
if (log.isDebugEnabled()) {
|
changeSet.set(key, value);
|
||||||
log.debug("Adding to ChangeSet: {}", key);
|
}
|
||||||
}
|
}
|
||||||
changeSet.set(key, value);
|
return null;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
return null;
|
}
|
||||||
}
|
|
||||||
});
|
/*
|
||||||
}
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.crossstore.ChangeSetPersister#getPersistentId(org.springframework.data.crossstore.ChangeSetBacked, org.springframework.data.crossstore.ChangeSet)
|
||||||
/*
|
*/
|
||||||
* (non-Javadoc)
|
public Object getPersistentId(ChangeSetBacked entity, ChangeSet cs) throws DataAccessException {
|
||||||
* @see org.springframework.data.crossstore.ChangeSetPersister#getPersistentId(org.springframework.data.crossstore.ChangeSetBacked, org.springframework.data.crossstore.ChangeSet)
|
if (log.isDebugEnabled()) {
|
||||||
*/
|
log.debug("getPersistentId called on {}", entity);
|
||||||
public Object getPersistentId(ChangeSetBacked entity, ChangeSet cs) throws DataAccessException {
|
}
|
||||||
if (log.isDebugEnabled()) {
|
if (entityManagerFactory == null) {
|
||||||
log.debug("getPersistentId called on {}", entity);
|
throw new DataAccessResourceFailureException("EntityManagerFactory cannot be null");
|
||||||
}
|
}
|
||||||
if (entityManagerFactory == null) {
|
|
||||||
throw new DataAccessResourceFailureException("EntityManagerFactory cannot be null");
|
return entityManagerFactory.getPersistenceUnitUtil().getIdentifier(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
return entityManagerFactory.getPersistenceUnitUtil().getIdentifier(entity);
|
/*
|
||||||
}
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.crossstore.ChangeSetPersister#persistState(org.springframework.data.crossstore.ChangeSetBacked, org.springframework.data.crossstore.ChangeSet)
|
||||||
/*
|
*/
|
||||||
* (non-Javadoc)
|
public Object persistState(ChangeSetBacked entity, ChangeSet cs) throws DataAccessException {
|
||||||
* @see org.springframework.data.crossstore.ChangeSetPersister#persistState(org.springframework.data.crossstore.ChangeSetBacked, org.springframework.data.crossstore.ChangeSet)
|
if (cs == null) {
|
||||||
*/
|
log.debug("Flush: changeset was null, nothing to flush.");
|
||||||
public Object persistState(ChangeSetBacked entity, ChangeSet cs) throws DataAccessException {
|
return 0L;
|
||||||
if (cs == null) {
|
}
|
||||||
log.debug("Flush: changeset was null, nothing to flush.");
|
|
||||||
return 0L;
|
if (log.isDebugEnabled()) {
|
||||||
}
|
log.debug("Flush: changeset: {}", cs.getValues());
|
||||||
|
}
|
||||||
if (log.isDebugEnabled()) {
|
|
||||||
log.debug("Flush: changeset: {}", cs.getValues());
|
String collName = getCollectionNameForEntity(entity.getClass());
|
||||||
}
|
if (mongoTemplate.getCollection(collName) == null) {
|
||||||
|
mongoTemplate.createCollection(collName);
|
||||||
String collName = getCollectionNameForEntity(entity.getClass());
|
}
|
||||||
if (mongoTemplate.getCollection(collName) == null) {
|
|
||||||
mongoTemplate.createCollection(collName);
|
for (String key : cs.getValues().keySet()) {
|
||||||
}
|
if (key != null && !key.startsWith("_") && !key.equals(ChangeSetPersister.ID_KEY)) {
|
||||||
|
Object value = cs.getValues().get(key);
|
||||||
for (String key : cs.getValues().keySet()) {
|
final DBObject dbQuery = new BasicDBObject();
|
||||||
if (key != null && !key.startsWith("_") && !key.equals(ChangeSetPersister.ID_KEY)) {
|
dbQuery.put(ENTITY_ID, getPersistentId(entity, cs));
|
||||||
Object value = cs.getValues().get(key);
|
dbQuery.put(ENTITY_CLASS, entity.getClass().getName());
|
||||||
final Document dbQuery = new Document();
|
dbQuery.put(ENTITY_FIELD_NAME, key);
|
||||||
dbQuery.put(ENTITY_ID, getPersistentId(entity, cs));
|
DBObject dbId = mongoTemplate.execute(collName, new CollectionCallback<DBObject>() {
|
||||||
dbQuery.put(ENTITY_CLASS, entity.getClass().getName());
|
public DBObject doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||||
dbQuery.put(ENTITY_FIELD_NAME, key);
|
return collection.findOne(dbQuery);
|
||||||
final Document dbId = mongoTemplate.execute(collName, new CollectionCallback<Document>() {
|
}
|
||||||
public Document doInCollection(MongoCollection<Document> collection)
|
});
|
||||||
throws MongoException, DataAccessException {
|
if (value == null) {
|
||||||
Document id = collection.find(dbQuery).first();
|
if (log.isDebugEnabled()) {
|
||||||
return id;
|
log.debug("Flush: removing: {}", dbQuery);
|
||||||
}
|
}
|
||||||
});
|
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
|
||||||
|
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||||
if (value == null) {
|
collection.remove(dbQuery);
|
||||||
if (log.isDebugEnabled()) {
|
return null;
|
||||||
log.debug("Flush: removing: {}", dbQuery);
|
}
|
||||||
}
|
});
|
||||||
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
|
} else {
|
||||||
public Object doInCollection(MongoCollection<Document> collection)
|
final DBObject dbDoc = new BasicDBObject();
|
||||||
throws MongoException, DataAccessException {
|
dbDoc.putAll(dbQuery);
|
||||||
DeleteResult dr = collection.deleteMany(dbQuery);
|
if (log.isDebugEnabled()) {
|
||||||
return null;
|
log.debug("Flush: saving: {}", dbQuery);
|
||||||
}
|
}
|
||||||
});
|
mongoTemplate.getConverter().write(value, dbDoc);
|
||||||
} else {
|
dbDoc.put(ENTITY_FIELD_CLASS, value.getClass().getName());
|
||||||
final Document dbDoc = new Document();
|
if (dbId != null) {
|
||||||
dbDoc.putAll(dbQuery);
|
dbDoc.put("_id", dbId.get("_id"));
|
||||||
if (log.isDebugEnabled()) {
|
}
|
||||||
log.debug("Flush: saving: {}", dbQuery);
|
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
|
||||||
}
|
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||||
mongoTemplate.getConverter().write(value, dbDoc);
|
collection.save(dbDoc);
|
||||||
dbDoc.put(ENTITY_FIELD_CLASS, value.getClass().getName());
|
return null;
|
||||||
if (dbId != null) {
|
}
|
||||||
dbDoc.put("_id", dbId.get("_id"));
|
});
|
||||||
}
|
}
|
||||||
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
|
}
|
||||||
public Object doInCollection(MongoCollection<Document> collection)
|
}
|
||||||
throws MongoException, DataAccessException {
|
return 0L;
|
||||||
|
}
|
||||||
if (dbId != null) {
|
|
||||||
collection.replaceOne(Filters.eq("_id", dbId.get("_id")), dbDoc);
|
/**
|
||||||
} else {
|
* Returns the collection the given entity type shall be persisted to.
|
||||||
|
*
|
||||||
if (dbDoc.containsKey("_id") && dbDoc.get("_id") == null) {
|
* @param entityClass must not be {@literal null}.
|
||||||
dbDoc.remove("_id");
|
* @return
|
||||||
}
|
*/
|
||||||
collection.insertOne(dbDoc);
|
private String getCollectionNameForEntity(Class<? extends ChangeSetBacked> entityClass) {
|
||||||
}
|
return mongoTemplate.getCollectionName(entityClass);
|
||||||
return null;
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0L;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the collection the given entity type shall be persisted to.
|
|
||||||
*
|
|
||||||
* @param entityClass must not be {@literal null}.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private String getCollectionNameForEntity(Class<? extends ChangeSetBacked> entityClass) {
|
|
||||||
return mongoTemplate.getCollectionName(entityClass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2019 the original author or authors.
|
* Copyright 2011 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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);
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2019 the original author or authors.
|
* Copyright 2011 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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 {
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2019 the original author or authors.
|
* Copyright 2011-2013 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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;
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2019 the original author or authors.
|
* Copyright 2011 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2019 the original author or authors.
|
* Copyright 2011 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2019 the original author or authors.
|
* Copyright 2011 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
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>
|
||||||
|
|
||||||
@@ -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.DATAMONGO-REACTIVE-SKIP-TAKE-SNAPSHOT</version>
|
<version>1.10.0.RELEASE</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
@@ -36,15 +35,8 @@
|
|||||||
<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)
|
||||||
30
spring-data-mongodb-log4j/pom.xml
Normal file
30
spring-data-mongodb-log4j/pom.xml
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?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">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.data</groupId>
|
||||||
|
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||||
|
<version>1.10.0.RELEASE</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>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<!-- Logging -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>log4j</groupId>
|
||||||
|
<artifactId>log4j</artifactId>
|
||||||
|
<version>${log4j}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,298 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011-2016 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.springframework.data.mongodb.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 the original author 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.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-2016 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.springframework.data.mongodb.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-2017 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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 https://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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
@@ -11,16 +11,13 @@
|
|||||||
<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.DATAMONGO-REACTIVE-SKIP-TAKE-SNAPSHOT</version>
|
<version>1.10.0.RELEASE</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>
|
|
||||||
<multithreadedtc>1.01</multithreadedtc>
|
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@@ -81,80 +78,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 +88,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 +126,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>
|
||||||
|
|
||||||
@@ -216,6 +147,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
<artifactId>jackson-databind</artifactId>
|
<artifactId>jackson-databind</artifactId>
|
||||||
|
<version>${jackson}</version>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</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>
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015-2019 the original author or authors.
|
* Copyright 2015 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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}.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2012 the original author 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.DataAccessResourceFailureException;
|
||||||
|
import org.springframework.data.authentication.UserCredentials;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception being thrown in case we cannot connect to a MongoDB instance.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
public class CannotGetMongoDbConnectionException extends DataAccessResourceFailureException {
|
||||||
|
|
||||||
|
private final UserCredentials credentials;
|
||||||
|
private final String database;
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1172099106475265589L;
|
||||||
|
|
||||||
|
public CannotGetMongoDbConnectionException(String msg, Throwable cause) {
|
||||||
|
super(msg, cause);
|
||||||
|
this.database = null;
|
||||||
|
this.credentials = UserCredentials.NO_CREDENTIALS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CannotGetMongoDbConnectionException(String msg) {
|
||||||
|
this(msg, null, UserCredentials.NO_CREDENTIALS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CannotGetMongoDbConnectionException(String msg, String database, UserCredentials credentials) {
|
||||||
|
super(msg);
|
||||||
|
this.database = database;
|
||||||
|
this.credentials = credentials;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link UserCredentials} that were used when trying to connect to the MongoDB instance.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public UserCredentials getCredentials() {
|
||||||
|
return this.credentials;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of the database trying to be accessed.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getDatabase() {
|
||||||
|
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
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.data.mongodb;
|
|
||||||
|
|
||||||
import org.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
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.data.mongodb;
|
|
||||||
|
|
||||||
import 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2019 the original author or authors.
|
* Copyright 2010-2011 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2019 the original author or authors.
|
* Copyright 2011 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.data.mongodb;
|
|
||||||
|
|
||||||
import org.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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2019 the original author or authors.
|
* Copyright 2011-2013 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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,108 +15,41 @@
|
|||||||
*/
|
*/
|
||||||
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.
|
||||||
*
|
*
|
||||||
* @param dbName must not be {@literal null} or empty.
|
* @param dbName must not be {@literal null} or empty.
|
||||||
* @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}.
|
||||||
*
|
*
|
||||||
* @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
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.data.mongodb;
|
|
||||||
|
|
||||||
import org.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
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.data.mongodb;
|
|
||||||
|
|
||||||
import 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
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.data.mongodb;
|
|
||||||
|
|
||||||
import org.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
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.data.mongodb;
|
|
||||||
|
|
||||||
import org.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
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.data.mongodb;
|
|
||||||
|
|
||||||
import 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
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.data.mongodb;
|
|
||||||
|
|
||||||
import 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
|
|
||||||
*
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@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;
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2019 the original author or authors.
|
* Copyright 2010-2011 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.data.mongodb.config;
|
|
||||||
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.data.mongodb.MongoDbFactory;
|
|
||||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
|
||||||
import org.springframework.data.mongodb.core.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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,118 +1,297 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2019 the original author or authors.
|
* Copyright 2011-2016 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* 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.config;
|
package org.springframework.data.mongodb.config;
|
||||||
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import java.util.Collection;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import java.util.Collections;
|
||||||
import org.springframework.data.mongodb.MongoDbFactory;
|
import java.util.HashSet;
|
||||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
import java.util.Set;
|
||||||
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
|
|
||||||
import org.springframework.data.mongodb.core.convert.DbRefResolver;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
|
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
||||||
import org.springframework.data.mongodb.core.mapping.Document;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.core.convert.converter.Converter;
|
||||||
|
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||||
import com.mongodb.MongoClient;
|
import org.springframework.data.annotation.Persistent;
|
||||||
|
import org.springframework.data.authentication.UserCredentials;
|
||||||
/**
|
import org.springframework.data.mapping.context.MappingContextIsNewStrategyFactory;
|
||||||
* Base class for Spring Data MongoDB configuration using JavaConfig with {@link com.mongodb.MongoClient}.
|
import org.springframework.data.mapping.model.CamelCaseAbbreviatingFieldNamingStrategy;
|
||||||
* <p />
|
import org.springframework.data.mapping.model.FieldNamingStrategy;
|
||||||
* <strong>INFO:</strong>In case you want to use {@link com.mongodb.client.MongoClients} for configuration please refer
|
import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy;
|
||||||
* to {@link AbstractMongoClientConfiguration}.
|
import org.springframework.data.mongodb.MongoDbFactory;
|
||||||
*
|
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||||
* @author Mark Pollack
|
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
|
||||||
* @author Oliver Gierke
|
import org.springframework.data.mongodb.core.convert.CustomConversions;
|
||||||
* @author Thomas Darimont
|
import org.springframework.data.mongodb.core.convert.DbRefResolver;
|
||||||
* @author Ryan Tenney
|
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
|
||||||
* @author Christoph Strobl
|
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
|
||||||
* @author Mark Paluch
|
import org.springframework.data.mongodb.core.mapping.Document;
|
||||||
* @see MongoConfigurationSupport
|
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||||
* @see AbstractMongoClientConfiguration
|
import org.springframework.data.support.CachingIsNewStrategyFactory;
|
||||||
*/
|
import org.springframework.data.support.IsNewStrategyFactory;
|
||||||
@Configuration
|
import org.springframework.util.ClassUtils;
|
||||||
public abstract class AbstractMongoConfiguration extends MongoConfigurationSupport {
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
import com.mongodb.Mongo;
|
||||||
* Return the {@link MongoClient} instance to connect to. Annotate with {@link Bean} in case you want to expose a
|
import com.mongodb.MongoClient;
|
||||||
* {@link MongoClient} instance to the {@link org.springframework.context.ApplicationContext}.
|
|
||||||
*
|
/**
|
||||||
* @return
|
* Base class for Spring Data MongoDB configuration using JavaConfig.
|
||||||
*/
|
*
|
||||||
public abstract MongoClient mongoClient();
|
* @author Mark Pollack
|
||||||
|
* @author Oliver Gierke
|
||||||
/**
|
* @author Thomas Darimont
|
||||||
* Creates a {@link MongoTemplate}.
|
* @author Ryan Tenney
|
||||||
*
|
* @author Christoph Strobl
|
||||||
* @return
|
*/
|
||||||
*/
|
@Configuration
|
||||||
@Bean
|
public abstract class AbstractMongoConfiguration {
|
||||||
public MongoTemplate mongoTemplate() throws Exception {
|
|
||||||
return new MongoTemplate(mongoDbFactory(), mappingMongoConverter());
|
/**
|
||||||
}
|
* Return the name of the database to connect to.
|
||||||
|
*
|
||||||
/**
|
* @return must not be {@literal null}.
|
||||||
* Creates a {@link SimpleMongoDbFactory} to be used by the {@link MongoTemplate}. Will use the {@link MongoClient}
|
*/
|
||||||
* instance configured in {@link #mongoClient()}.
|
protected abstract String getDatabaseName();
|
||||||
*
|
|
||||||
* @see #mongoClient()
|
/**
|
||||||
* @see #mongoTemplate()
|
* Return the name of the authentication database to use. Defaults to {@literal null} and will turn into the value
|
||||||
* @return
|
* returned by {@link #getDatabaseName()} later on effectively.
|
||||||
*/
|
*
|
||||||
@Bean
|
* @return
|
||||||
public MongoDbFactory mongoDbFactory() {
|
* @deprecated since 1.7. {@link MongoClient} should hold authentication data within
|
||||||
return new SimpleMongoDbFactory(mongoClient(), getDatabaseName());
|
* {@link MongoClient#getCredentialsList()}
|
||||||
}
|
*/
|
||||||
|
@Deprecated
|
||||||
/**
|
protected String getAuthenticationDatabaseName() {
|
||||||
* Return the base package to scan for mapped {@link Document}s. Will return the package name of the configuration
|
return null;
|
||||||
* 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 {@link Mongo} instance to connect to. Annotate with {@link Bean} in case you want to expose a
|
||||||
* @return the base package to scan for mapped {@link Document} classes or {@literal null} to not enable scanning for
|
* {@link Mongo} instance to the {@link org.springframework.context.ApplicationContext}.
|
||||||
* entities.
|
*
|
||||||
* @deprecated use {@link #getMappingBasePackages()} instead.
|
* @return
|
||||||
*/
|
* @throws Exception
|
||||||
@Deprecated
|
*/
|
||||||
@Nullable
|
public abstract Mongo mongo() throws Exception;
|
||||||
protected String getMappingBasePackage() {
|
|
||||||
|
/**
|
||||||
Package mappingBasePackage = getClass().getPackage();
|
* Creates a {@link MongoTemplate}.
|
||||||
return mappingBasePackage == null ? null : mappingBasePackage.getName();
|
*
|
||||||
}
|
* @return
|
||||||
|
* @throws Exception
|
||||||
/**
|
*/
|
||||||
* Creates a {@link MappingMongoConverter} using the configured {@link #mongoDbFactory()} and
|
@Bean
|
||||||
* {@link #mongoMappingContext()}. Will get {@link #customConversions()} applied.
|
public MongoTemplate mongoTemplate() throws Exception {
|
||||||
*
|
return new MongoTemplate(mongoDbFactory(), mappingMongoConverter());
|
||||||
* @see #customConversions()
|
}
|
||||||
* @see #mongoMappingContext()
|
|
||||||
* @see #mongoDbFactory()
|
/**
|
||||||
* @return
|
* Creates a {@link SimpleMongoDbFactory} to be used by the {@link MongoTemplate}. Will use the {@link Mongo} instance
|
||||||
* @throws Exception
|
* configured in {@link #mongo()}.
|
||||||
*/
|
*
|
||||||
@Bean
|
* @see #mongo()
|
||||||
public MappingMongoConverter mappingMongoConverter() throws Exception {
|
* @see #mongoTemplate()
|
||||||
|
* @return
|
||||||
DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory());
|
* @throws Exception
|
||||||
MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, mongoMappingContext());
|
*/
|
||||||
converter.setCustomConversions(customConversions());
|
@Bean
|
||||||
|
public MongoDbFactory mongoDbFactory() throws Exception {
|
||||||
return converter;
|
return new SimpleMongoDbFactory(mongo(), getDatabaseName(), getUserCredentials(), getAuthenticationDatabaseName());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
/**
|
||||||
|
* Return the base package to scan for mapped {@link Document}s. Will return the package name of the configuration
|
||||||
|
* class' (the concrete class, not this one here) by default. So if you have a {@code com.acme.AppConfig} extending
|
||||||
|
* {@link AbstractMongoConfiguration} the base package will be considered {@code com.acme} unless the method is
|
||||||
|
* overridden to implement alternate behavior.
|
||||||
|
*
|
||||||
|
* @return the base package to scan for mapped {@link Document} classes or {@literal null} to not enable scanning for
|
||||||
|
* entities.
|
||||||
|
* @deprecated use {@link #getMappingBasePackages()} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
protected String getMappingBasePackage() {
|
||||||
|
|
||||||
|
Package mappingBasePackage = getClass().getPackage();
|
||||||
|
return mappingBasePackage == null ? null : mappingBasePackage.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the base packages to scan for MongoDB mapped entities at startup. Will return the package name of the
|
||||||
|
* configuration class' (the concrete class, not this one here) by default. So if you have a
|
||||||
|
* {@code com.acme.AppConfig} extending {@link AbstractMongoConfiguration} the base package will be considered
|
||||||
|
* {@code com.acme} unless the method is overridden to implement alternate behavior.
|
||||||
|
*
|
||||||
|
* @return the base packages to scan for mapped {@link Document} classes or an empty collection to not enable scanning
|
||||||
|
* for entities.
|
||||||
|
* @since 1.10
|
||||||
|
*/
|
||||||
|
protected Collection<String> getMappingBasePackages() {
|
||||||
|
return Collections.singleton(getMappingBasePackage());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return {@link UserCredentials} to be used when connecting to the MongoDB instance or {@literal null} if none shall
|
||||||
|
* be used.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* @deprecated since 1.7. {@link MongoClient} should hold authentication data within
|
||||||
|
* {@link MongoClient#getCredentialsList()}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
protected UserCredentials getUserCredentials() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link MongoMappingContext} equipped with entity classes scanned from the mapping base package.
|
||||||
|
*
|
||||||
|
* @see #getMappingBasePackage()
|
||||||
|
* @return
|
||||||
|
* @throws ClassNotFoundException
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public MongoMappingContext mongoMappingContext() throws ClassNotFoundException {
|
||||||
|
|
||||||
|
MongoMappingContext mappingContext = new MongoMappingContext();
|
||||||
|
mappingContext.setInitialEntitySet(getInitialEntitySet());
|
||||||
|
mappingContext.setSimpleTypeHolder(customConversions().getSimpleTypeHolder());
|
||||||
|
mappingContext.setFieldNamingStrategy(fieldNamingStrategy());
|
||||||
|
|
||||||
|
return mappingContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@link MappingContextIsNewStrategyFactory} wrapped into a {@link CachingIsNewStrategyFactory}.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* @throws ClassNotFoundException
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public IsNewStrategyFactory isNewStrategyFactory() throws ClassNotFoundException {
|
||||||
|
return new CachingIsNewStrategyFactory(new MappingContextIsNewStrategyFactory(mongoMappingContext()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register custom {@link Converter}s in a {@link CustomConversions} object if required. These
|
||||||
|
* {@link CustomConversions} will be registered with the {@link #mappingMongoConverter()} and
|
||||||
|
* {@link #mongoMappingContext()}. Returns an empty {@link CustomConversions} instance by default.
|
||||||
|
*
|
||||||
|
* @return must not be {@literal null}.
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public CustomConversions customConversions() {
|
||||||
|
return new CustomConversions(Collections.emptyList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link MappingMongoConverter} using the configured {@link #mongoDbFactory()} and
|
||||||
|
* {@link #mongoMappingContext()}. Will get {@link #customConversions()} applied.
|
||||||
|
*
|
||||||
|
* @see #customConversions()
|
||||||
|
* @see #mongoMappingContext()
|
||||||
|
* @see #mongoDbFactory()
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public MappingMongoConverter mappingMongoConverter() throws Exception {
|
||||||
|
|
||||||
|
DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory());
|
||||||
|
MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, mongoMappingContext());
|
||||||
|
converter.setCustomConversions(customConversions());
|
||||||
|
|
||||||
|
return converter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scans the mapping base package for classes annotated with {@link Document}. By default, it scans for entities in
|
||||||
|
* all packages returned by {@link #getMappingBasePackages()}.
|
||||||
|
*
|
||||||
|
* @see #getMappingBasePackages()
|
||||||
|
* @return
|
||||||
|
* @throws ClassNotFoundException
|
||||||
|
*/
|
||||||
|
protected Set<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
|
||||||
|
|
||||||
|
Set<Class<?>> initialEntitySet = new HashSet<Class<?>>();
|
||||||
|
|
||||||
|
for (String basePackage : getMappingBasePackages()) {
|
||||||
|
initialEntitySet.addAll(scanForEntities(basePackage));
|
||||||
|
}
|
||||||
|
|
||||||
|
return initialEntitySet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scans the given base package for entities, i.e. MongoDB specific types annotated with {@link Document} and
|
||||||
|
* {@link Persistent}.
|
||||||
|
*
|
||||||
|
* @param basePackage must not be {@literal null}.
|
||||||
|
* @return
|
||||||
|
* @throws ClassNotFoundException
|
||||||
|
* @since 1.10
|
||||||
|
*/
|
||||||
|
protected Set<Class<?>> scanForEntities(String basePackage) throws ClassNotFoundException {
|
||||||
|
|
||||||
|
if (!StringUtils.hasText(basePackage)) {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<Class<?>> initialEntitySet = new HashSet<Class<?>>();
|
||||||
|
|
||||||
|
if (StringUtils.hasText(basePackage)) {
|
||||||
|
|
||||||
|
ClassPathScanningCandidateComponentProvider componentProvider = new ClassPathScanningCandidateComponentProvider(
|
||||||
|
false);
|
||||||
|
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Document.class));
|
||||||
|
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Persistent.class));
|
||||||
|
|
||||||
|
for (BeanDefinition candidate : componentProvider.findCandidateComponents(basePackage)) {
|
||||||
|
|
||||||
|
initialEntitySet
|
||||||
|
.add(ClassUtils.forName(candidate.getBeanClassName(), AbstractMongoConfiguration.class.getClassLoader()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return initialEntitySet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures whether to abbreviate field names for domain objects by configuring a
|
||||||
|
* {@link CamelCaseAbbreviatingFieldNamingStrategy} on the {@link MongoMappingContext} instance created. For advanced
|
||||||
|
* customization needs, consider overriding {@link #mappingMongoConverter()}.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected boolean abbreviateFieldNames() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures a {@link FieldNamingStrategy} on the {@link MongoMappingContext} instance created.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
protected FieldNamingStrategy fieldNamingStrategy() {
|
||||||
|
return abbreviateFieldNames() ? new CamelCaseAbbreviatingFieldNamingStrategy()
|
||||||
|
: PropertyNameFieldNamingStrategy.INSTANCE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.data.mongodb.config;
|
|
||||||
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.data.mongodb.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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2019 the original author or authors.
|
* Copyright 2011-2014 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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";
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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 "";
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2014 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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 {
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2019 the original author or authors.
|
* Copyright 2011-2014 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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,
|
||||||
@@ -51,15 +51,14 @@ import org.springframework.core.type.filter.AssignableTypeFilter;
|
|||||||
import org.springframework.core.type.filter.TypeFilter;
|
import org.springframework.core.type.filter.TypeFilter;
|
||||||
import org.springframework.data.annotation.Persistent;
|
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.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;
|
||||||
@@ -68,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 {
|
||||||
|
|
||||||
@@ -101,6 +98,8 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
|
|||||||
BeanDefinition conversionsDefinition = getCustomConversions(element, parserContext);
|
BeanDefinition conversionsDefinition = getCustomConversions(element, parserContext);
|
||||||
String ctxRef = potentiallyCreateMappingContext(element, parserContext, conversionsDefinition, id);
|
String ctxRef = potentiallyCreateMappingContext(element, parserContext, conversionsDefinition, id);
|
||||||
|
|
||||||
|
createIsNewStrategyFactoryBeanDefinition(ctxRef, parserContext, element);
|
||||||
|
|
||||||
// Need a reference to a Mongo instance
|
// Need a reference to a Mongo instance
|
||||||
String dbFactoryRef = element.getAttribute("db-factory-ref");
|
String dbFactoryRef = element.getAttribute("db-factory-ref");
|
||||||
if (!StringUtils.hasText(dbFactoryRef)) {
|
if (!StringUtils.hasText(dbFactoryRef)) {
|
||||||
@@ -121,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));
|
||||||
@@ -158,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");
|
||||||
@@ -180,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) {
|
||||||
@@ -198,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");
|
||||||
|
|
||||||
@@ -212,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);
|
||||||
@@ -263,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");
|
||||||
@@ -271,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) {
|
||||||
@@ -287,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();
|
||||||
@@ -304,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);
|
||||||
|
|
||||||
@@ -318,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());
|
||||||
}
|
}
|
||||||
@@ -326,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");
|
||||||
@@ -340,14 +327,28 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String createIsNewStrategyFactoryBeanDefinition(String mappingContextRef, ParserContext context,
|
||||||
|
Element element) {
|
||||||
|
|
||||||
|
BeanDefinitionBuilder mappingContextStrategyFactoryBuilder = BeanDefinitionBuilder
|
||||||
|
.rootBeanDefinition(MappingContextIsNewStrategyFactory.class);
|
||||||
|
mappingContextStrategyFactoryBuilder.addConstructorArgReference(mappingContextRef);
|
||||||
|
|
||||||
|
BeanComponentDefinitionBuilder builder = new BeanComponentDefinitionBuilder(element, context);
|
||||||
|
context.registerBeanComponent(builder.getComponent(mappingContextStrategyFactoryBuilder,
|
||||||
|
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 {
|
||||||
@@ -356,22 +357,19 @@ 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);
|
||||||
Assert.notNull(filters, "TypeFilters must not be null");
|
this.delegates = new HashSet<TypeFilter>(Arrays.asList(filters));
|
||||||
|
|
||||||
this.delegates = new HashSet<>(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)) {
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2019 the original author or authors.
|
* Copyright 2012-2014 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2016 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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()
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015-2019 the original author or authors.
|
* Copyright 2015 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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,187 +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
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.data.mongodb.config;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
|
||||||
import org.springframework.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.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.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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015-2019 the original author or authors.
|
* Copyright 2015 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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,6 @@
|
|||||||
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.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,19 +23,15 @@ 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.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import com.mongodb.MongoCredential;
|
import com.mongodb.MongoCredential;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a {@link String} to a Collection of {@link MongoCredential}.
|
* Parse a {@link String} to a Collection of {@link MongoCredential}.
|
||||||
*
|
*
|
||||||
* @author Christoph Strobl
|
* @author Christoph Strobl
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Stephen Tyler Conrad
|
|
||||||
* @author Mark Paluch
|
|
||||||
* @since 1.7
|
* @since 1.7
|
||||||
*/
|
*/
|
||||||
public class MongoCredentialPropertyEditor extends PropertyEditorSupport {
|
public class MongoCredentialPropertyEditor extends PropertyEditorSupport {
|
||||||
@@ -46,23 +39,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 +73,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 +95,6 @@ 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)) {
|
|
||||||
|
|
||||||
verifyUsernameAndPasswordPresent(userNameAndPassword);
|
|
||||||
verifyDatabasePresent(database);
|
|
||||||
credentials.add(MongoCredential.createScramSha256Credential(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 +115,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,51 +132,40 @@ 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(OPTIONS_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) {
|
|
||||||
throw new IllegalArgumentException(String.format("Query parameter '%s' has no value!", optionArgs[0]));
|
|
||||||
}
|
|
||||||
|
|
||||||
properties.put(optionArgs[0], optionArgs[1]);
|
properties.put(optionArgs[0], optionArgs[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,12 +195,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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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);
|
||||||
|
|||||||
@@ -1,76 +1,69 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2019 the original author or authors.
|
* Copyright 2011 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* 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.config;
|
package org.springframework.data.mongodb.config;
|
||||||
|
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||||
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
|
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
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.mongodb.core.MongoAdmin;
|
import org.springframework.data.mongodb.core.MongoAdmin;
|
||||||
import org.springframework.data.mongodb.monitor.*;
|
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;
|
||||||
|
|
||||||
/**
|
public class MongoJmxParser implements BeanDefinitionParser {
|
||||||
* @author Mark Pollack
|
|
||||||
* @author Thomas Risberg
|
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||||
* @author John Brisbin
|
String name = element.getAttribute("mongo-ref");
|
||||||
* @author Oliver Gierke
|
if (!StringUtils.hasText(name)) {
|
||||||
* @author Christoph Strobl
|
name = "mongo";
|
||||||
*/
|
}
|
||||||
public class MongoJmxParser implements BeanDefinitionParser {
|
registerJmxComponents(name, element, parserContext);
|
||||||
|
return null;
|
||||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
}
|
||||||
String name = element.getAttribute("mongo-ref");
|
|
||||||
if (!StringUtils.hasText(name)) {
|
protected void registerJmxComponents(String mongoRefName, Element element, ParserContext parserContext) {
|
||||||
name = BeanNames.MONGO_BEAN_NAME;
|
Object eleSource = parserContext.extractSource(element);
|
||||||
}
|
|
||||||
registerJmxComponents(name, element, parserContext);
|
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
|
||||||
return null;
|
|
||||||
}
|
createBeanDefEntry(AssertMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
|
||||||
|
createBeanDefEntry(BackgroundFlushingMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
|
||||||
protected void registerJmxComponents(String mongoRefName, Element element, ParserContext parserContext) {
|
createBeanDefEntry(BtreeIndexCounters.class, compositeDef, mongoRefName, eleSource, parserContext);
|
||||||
Object eleSource = parserContext.extractSource(element);
|
createBeanDefEntry(ConnectionMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
|
||||||
|
createBeanDefEntry(GlobalLockMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
|
||||||
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
|
createBeanDefEntry(MemoryMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
|
||||||
|
createBeanDefEntry(OperationCounters.class, compositeDef, mongoRefName, eleSource, parserContext);
|
||||||
createBeanDefEntry(AssertMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
|
createBeanDefEntry(ServerInfo.class, compositeDef, mongoRefName, eleSource, parserContext);
|
||||||
createBeanDefEntry(BackgroundFlushingMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
|
createBeanDefEntry(MongoAdmin.class, compositeDef, mongoRefName, eleSource, parserContext);
|
||||||
createBeanDefEntry(BtreeIndexCounters.class, compositeDef, mongoRefName, eleSource, parserContext);
|
|
||||||
createBeanDefEntry(ConnectionMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
|
parserContext.registerComponent(compositeDef);
|
||||||
createBeanDefEntry(GlobalLockMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
|
|
||||||
createBeanDefEntry(MemoryMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
|
}
|
||||||
createBeanDefEntry(OperationCounters.class, compositeDef, mongoRefName, eleSource, parserContext);
|
|
||||||
createBeanDefEntry(ServerInfo.class, compositeDef, mongoRefName, eleSource, parserContext);
|
protected void createBeanDefEntry(Class<?> clazz, CompositeComponentDefinition compositeDef, String mongoRefName,
|
||||||
createBeanDefEntry(MongoAdmin.class, compositeDef, mongoRefName, eleSource, parserContext);
|
Object eleSource, ParserContext parserContext) {
|
||||||
|
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
|
||||||
parserContext.registerComponent(compositeDef);
|
builder.getRawBeanDefinition().setSource(eleSource);
|
||||||
|
builder.addConstructorArgReference(mongoRefName);
|
||||||
}
|
BeanDefinition assertDef = builder.getBeanDefinition();
|
||||||
|
String assertName = parserContext.getReaderContext().registerWithGeneratedName(assertDef);
|
||||||
protected void createBeanDefEntry(Class<?> clazz, CompositeComponentDefinition compositeDef, String mongoRefName,
|
compositeDef.addNestedComponent(new BeanComponentDefinition(assertDef, assertName));
|
||||||
Object eleSource, ParserContext parserContext) {
|
}
|
||||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
|
|
||||||
builder.getRawBeanDefinition().setSource(eleSource);
|
}
|
||||||
builder.addConstructorArgReference(mongoRefName);
|
|
||||||
BeanDefinition assertDef = builder.getBeanDefinition();
|
|
||||||
String assertName = parserContext.getReaderContext().registerWithGeneratedName(assertDef);
|
|
||||||
compositeDef.addNestedComponent(new BeanComponentDefinition(assertDef, assertName));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2019 the original author or authors.
|
* Copyright 2011-2015 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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-2015 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.springframework.data.mongodb.config;
|
||||||
|
|
||||||
|
import 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,170 +1,206 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2019 the original author or authors.
|
* Copyright 2011-2015 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* 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.config;
|
package org.springframework.data.mongodb.config;
|
||||||
|
|
||||||
import static org.springframework.data.config.ParsingUtils.*;
|
import static org.springframework.data.config.ParsingUtils.*;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.beans.factory.config.CustomEditorConfigurer;
|
import org.springframework.beans.factory.config.CustomEditorConfigurer;
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
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.util.xml.DomUtils;
|
import org.springframework.data.mongodb.core.MongoOptionsFactoryBean;
|
||||||
import org.w3c.dom.Element;
|
import org.springframework.util.xml.DomUtils;
|
||||||
|
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 Oliver Gierke
|
* @author Mark Pollack
|
||||||
* @author Thomas Darimont
|
* @author Oliver Gierke
|
||||||
* @author Christoph Strobl
|
* @author Thomas Darimont
|
||||||
*/
|
* @author Christoph Strobl
|
||||||
@SuppressWarnings("deprecation")
|
*/
|
||||||
abstract class MongoParsingUtils {
|
@SuppressWarnings("deprecation")
|
||||||
|
abstract class MongoParsingUtils {
|
||||||
private MongoParsingUtils() {}
|
|
||||||
|
private MongoParsingUtils() {}
|
||||||
/**
|
|
||||||
* Parses the mongo replica-set element.
|
/**
|
||||||
*
|
* Parses the mongo replica-set element.
|
||||||
* @param parserContext the parser context
|
*
|
||||||
* @param element the mongo element
|
* @param parserContext the parser context
|
||||||
* @param mongoBuilder the bean definition builder to populate
|
* @param element the mongo element
|
||||||
* @return
|
* @param mongoBuilder the bean definition builder to populate
|
||||||
*/
|
* @return
|
||||||
static void parseReplicaSet(Element element, BeanDefinitionBuilder mongoBuilder) {
|
*/
|
||||||
setPropertyValue(mongoBuilder, element, "replica-set", "replicaSetSeeds");
|
static void parseReplicaSet(Element element, BeanDefinitionBuilder mongoBuilder) {
|
||||||
}
|
setPropertyValue(mongoBuilder, element, "replica-set", "replicaSetSeeds");
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Parses the {@code mongo:client-options} sub-element. Populates the given attribute factory with the proper
|
/**
|
||||||
* attributes.
|
* Parses the {@code mongo:options} sub-element. Populates the given attribute factory with the proper attributes.
|
||||||
*
|
*
|
||||||
* @param element must not be {@literal null}.
|
* @return true if parsing actually occured, {@literal false} otherwise
|
||||||
* @param mongoClientBuilder must not be {@literal null}.
|
*/
|
||||||
* @return
|
static boolean parseMongoOptions(Element element, BeanDefinitionBuilder mongoBuilder) {
|
||||||
* @since 1.7
|
|
||||||
*/
|
Element optionsElement = DomUtils.getChildElementByTagName(element, "options");
|
||||||
public static boolean parseMongoClientOptions(Element element, BeanDefinitionBuilder mongoClientBuilder) {
|
|
||||||
|
if (optionsElement == null) {
|
||||||
Element optionsElement = DomUtils.getChildElementByTagName(element, "client-options");
|
return false;
|
||||||
|
}
|
||||||
if (optionsElement == null) {
|
|
||||||
return false;
|
BeanDefinitionBuilder optionsDefBuilder = BeanDefinitionBuilder
|
||||||
}
|
.genericBeanDefinition(MongoOptionsFactoryBean.class);
|
||||||
|
|
||||||
BeanDefinitionBuilder clientOptionsDefBuilder = BeanDefinitionBuilder
|
setPropertyValue(optionsDefBuilder, optionsElement, "connections-per-host", "connectionsPerHost");
|
||||||
.genericBeanDefinition(MongoClientOptionsFactoryBean.class);
|
setPropertyValue(optionsDefBuilder, optionsElement, "threads-allowed-to-block-for-connection-multiplier",
|
||||||
|
"threadsAllowedToBlockForConnectionMultiplier");
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "description", "description");
|
setPropertyValue(optionsDefBuilder, optionsElement, "max-wait-time", "maxWaitTime");
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "min-connections-per-host", "minConnectionsPerHost");
|
setPropertyValue(optionsDefBuilder, optionsElement, "connect-timeout", "connectTimeout");
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "connections-per-host", "connectionsPerHost");
|
setPropertyValue(optionsDefBuilder, optionsElement, "socket-timeout", "socketTimeout");
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "threads-allowed-to-block-for-connection-multiplier",
|
setPropertyValue(optionsDefBuilder, optionsElement, "socket-keep-alive", "socketKeepAlive");
|
||||||
"threadsAllowedToBlockForConnectionMultiplier");
|
setPropertyValue(optionsDefBuilder, optionsElement, "auto-connect-retry", "autoConnectRetry");
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "max-wait-time", "maxWaitTime");
|
setPropertyValue(optionsDefBuilder, optionsElement, "max-auto-connect-retry-time", "maxAutoConnectRetryTime");
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "max-connection-idle-time", "maxConnectionIdleTime");
|
setPropertyValue(optionsDefBuilder, optionsElement, "write-number", "writeNumber");
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "max-connection-life-time", "maxConnectionLifeTime");
|
setPropertyValue(optionsDefBuilder, optionsElement, "write-timeout", "writeTimeout");
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "connect-timeout", "connectTimeout");
|
setPropertyValue(optionsDefBuilder, optionsElement, "write-fsync", "writeFsync");
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "socket-timeout", "socketTimeout");
|
setPropertyValue(optionsDefBuilder, optionsElement, "slave-ok", "slaveOk");
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "socket-keep-alive", "socketKeepAlive");
|
setPropertyValue(optionsDefBuilder, optionsElement, "ssl", "ssl");
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "read-preference", "readPreference");
|
setPropertyReference(optionsDefBuilder, optionsElement, "ssl-socket-factory-ref", "sslSocketFactory");
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "write-concern", "writeConcern");
|
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "heartbeat-frequency", "heartbeatFrequency");
|
mongoBuilder.addPropertyValue("mongoOptions", optionsDefBuilder.getBeanDefinition());
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "min-heartbeat-frequency", "minHeartbeatFrequency");
|
return true;
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "heartbeat-connect-timeout", "heartbeatConnectTimeout");
|
}
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "heartbeat-socket-timeout", "heartbeatSocketTimeout");
|
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "ssl", "ssl");
|
/**
|
||||||
setPropertyReference(clientOptionsDefBuilder, optionsElement, "ssl-socket-factory-ref", "sslSocketFactory");
|
* Parses the {@code mongo:client-options} sub-element. Populates the given attribute factory with the proper
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "server-selection-timeout", "serverSelectionTimeout");
|
* attributes.
|
||||||
|
*
|
||||||
mongoClientBuilder.addPropertyValue("mongoClientOptions", clientOptionsDefBuilder.getBeanDefinition());
|
* @param element must not be {@literal null}.
|
||||||
|
* @param mongoClientBuilder must not be {@literal null}.
|
||||||
return true;
|
* @return
|
||||||
}
|
* @since 1.7
|
||||||
|
*/
|
||||||
/**
|
public static boolean parseMongoClientOptions(Element element, BeanDefinitionBuilder mongoClientBuilder) {
|
||||||
* Returns the {@link BeanDefinitionBuilder} to build a {@link BeanDefinition} for a
|
|
||||||
* {@link WriteConcernPropertyEditor}.
|
Element optionsElement = DomUtils.getChildElementByTagName(element, "client-options");
|
||||||
*
|
|
||||||
* @return
|
if (optionsElement == null) {
|
||||||
*/
|
return false;
|
||||||
static BeanDefinitionBuilder getWriteConcernPropertyEditorBuilder() {
|
}
|
||||||
|
|
||||||
Map<String, Class<?>> customEditors = new ManagedMap<String, Class<?>>();
|
BeanDefinitionBuilder clientOptionsDefBuilder = BeanDefinitionBuilder
|
||||||
customEditors.put("com.mongodb.WriteConcern", WriteConcernPropertyEditor.class);
|
.genericBeanDefinition(MongoClientOptionsFactoryBean.class);
|
||||||
|
|
||||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class);
|
setPropertyValue(clientOptionsDefBuilder, optionsElement, "description", "description");
|
||||||
builder.addPropertyValue("customEditors", customEditors);
|
setPropertyValue(clientOptionsDefBuilder, optionsElement, "min-connections-per-host", "minConnectionsPerHost");
|
||||||
|
setPropertyValue(clientOptionsDefBuilder, optionsElement, "connections-per-host", "connectionsPerHost");
|
||||||
return builder;
|
setPropertyValue(clientOptionsDefBuilder, optionsElement, "threads-allowed-to-block-for-connection-multiplier",
|
||||||
}
|
"threadsAllowedToBlockForConnectionMultiplier");
|
||||||
|
setPropertyValue(clientOptionsDefBuilder, optionsElement, "max-wait-time", "maxWaitTime");
|
||||||
/**
|
setPropertyValue(clientOptionsDefBuilder, optionsElement, "max-connection-idle-time", "maxConnectionIdleTime");
|
||||||
* One should only register one bean definition but want to have the convenience of using
|
setPropertyValue(clientOptionsDefBuilder, optionsElement, "max-connection-life-time", "maxConnectionLifeTime");
|
||||||
* AbstractSingleBeanDefinitionParser but have the side effect of registering a 'default' property editor with the
|
setPropertyValue(clientOptionsDefBuilder, optionsElement, "connect-timeout", "connectTimeout");
|
||||||
* container.
|
setPropertyValue(clientOptionsDefBuilder, optionsElement, "socket-timeout", "socketTimeout");
|
||||||
*/
|
setPropertyValue(clientOptionsDefBuilder, optionsElement, "socket-keep-alive", "socketKeepAlive");
|
||||||
static BeanDefinitionBuilder getServerAddressPropertyEditorBuilder() {
|
setPropertyValue(clientOptionsDefBuilder, optionsElement, "read-preference", "readPreference");
|
||||||
|
setPropertyValue(clientOptionsDefBuilder, optionsElement, "write-concern", "writeConcern");
|
||||||
Map<String, String> customEditors = new ManagedMap<String, String>();
|
setPropertyValue(clientOptionsDefBuilder, optionsElement, "heartbeat-frequency", "heartbeatFrequency");
|
||||||
customEditors.put("com.mongodb.ServerAddress[]",
|
setPropertyValue(clientOptionsDefBuilder, optionsElement, "min-heartbeat-frequency", "minHeartbeatFrequency");
|
||||||
"org.springframework.data.mongodb.config.ServerAddressPropertyEditor");
|
setPropertyValue(clientOptionsDefBuilder, optionsElement, "heartbeat-connect-timeout", "heartbeatConnectTimeout");
|
||||||
|
setPropertyValue(clientOptionsDefBuilder, optionsElement, "heartbeat-socket-timeout", "heartbeatSocketTimeout");
|
||||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class);
|
setPropertyValue(clientOptionsDefBuilder, optionsElement, "ssl", "ssl");
|
||||||
builder.addPropertyValue("customEditors", customEditors);
|
setPropertyReference(clientOptionsDefBuilder, optionsElement, "ssl-socket-factory-ref", "sslSocketFactory");
|
||||||
return builder;
|
|
||||||
}
|
mongoClientBuilder.addPropertyValue("mongoClientOptions", clientOptionsDefBuilder.getBeanDefinition());
|
||||||
|
|
||||||
/**
|
return true;
|
||||||
* Returns the {@link BeanDefinitionBuilder} to build a {@link BeanDefinition} for a
|
}
|
||||||
* {@link ReadPreferencePropertyEditor}.
|
|
||||||
*
|
/**
|
||||||
* @return
|
* Returns the {@link BeanDefinitionBuilder} to build a {@link BeanDefinition} for a
|
||||||
* @since 1.7
|
* {@link WriteConcernPropertyEditor}.
|
||||||
*/
|
*
|
||||||
static BeanDefinitionBuilder getReadPreferencePropertyEditorBuilder() {
|
* @return
|
||||||
|
*/
|
||||||
Map<String, Class<?>> customEditors = new ManagedMap<String, Class<?>>();
|
static BeanDefinitionBuilder getWriteConcernPropertyEditorBuilder() {
|
||||||
customEditors.put("com.mongodb.ReadPreference", ReadPreferencePropertyEditor.class);
|
|
||||||
|
Map<String, Class<?>> customEditors = new ManagedMap<String, Class<?>>();
|
||||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class);
|
customEditors.put("com.mongodb.WriteConcern", WriteConcernPropertyEditor.class);
|
||||||
builder.addPropertyValue("customEditors", customEditors);
|
|
||||||
|
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class);
|
||||||
return builder;
|
builder.addPropertyValue("customEditors", customEditors);
|
||||||
}
|
|
||||||
|
return builder;
|
||||||
/**
|
}
|
||||||
* Returns the {@link BeanDefinitionBuilder} to build a {@link BeanDefinition} for a
|
|
||||||
* {@link MongoCredentialPropertyEditor}.
|
/**
|
||||||
*
|
* One should only register one bean definition but want to have the convenience of using
|
||||||
* @return
|
* AbstractSingleBeanDefinitionParser but have the side effect of registering a 'default' property editor with the
|
||||||
* @since 1.7
|
* container.
|
||||||
*/
|
*/
|
||||||
static BeanDefinitionBuilder getMongoCredentialPropertyEditor() {
|
static BeanDefinitionBuilder getServerAddressPropertyEditorBuilder() {
|
||||||
|
|
||||||
Map<String, Class<?>> customEditors = new ManagedMap<String, Class<?>>();
|
Map<String, String> customEditors = new ManagedMap<String, String>();
|
||||||
customEditors.put("com.mongodb.MongoCredential[]", MongoCredentialPropertyEditor.class);
|
customEditors.put("com.mongodb.ServerAddress[]",
|
||||||
|
"org.springframework.data.mongodb.config.ServerAddressPropertyEditor");
|
||||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class);
|
|
||||||
builder.addPropertyValue("customEditors", customEditors);
|
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class);
|
||||||
|
builder.addPropertyValue("customEditors", customEditors);
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link BeanDefinitionBuilder} to build a {@link BeanDefinition} for a
|
||||||
|
* {@link ReadPreferencePropertyEditor}.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* @since 1.7
|
||||||
|
*/
|
||||||
|
static BeanDefinitionBuilder getReadPreferencePropertyEditorBuilder() {
|
||||||
|
|
||||||
|
Map<String, Class<?>> customEditors = new ManagedMap<String, Class<?>>();
|
||||||
|
customEditors.put("com.mongodb.ReadPreference", ReadPreferencePropertyEditor.class);
|
||||||
|
|
||||||
|
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class);
|
||||||
|
builder.addPropertyValue("customEditors", customEditors);
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link BeanDefinitionBuilder} to build a {@link BeanDefinition} for a
|
||||||
|
* {@link MongoCredentialPropertyEditor}.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* @since 1.7
|
||||||
|
*/
|
||||||
|
static BeanDefinitionBuilder getMongoCredentialPropertyEditor() {
|
||||||
|
|
||||||
|
Map<String, Class<?>> customEditors = new ManagedMap<String, Class<?>>();
|
||||||
|
customEditors.put("com.mongodb.MongoCredential[]", MongoCredentialPropertyEditor.class);
|
||||||
|
|
||||||
|
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class);
|
||||||
|
builder.addPropertyValue("customEditors", customEditors);
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2019 the original author or authors.
|
* Copyright 2011-2014 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015-2019 the original author or authors.
|
* Copyright 2015 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2019 the original author or authors.
|
* Copyright 2011-2013 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2019 the original author or authors.
|
* Copyright 2012 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2019 the original author or authors.
|
* Copyright 2011 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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;
|
||||||
|
|
||||||
|
|||||||
@@ -1,170 +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
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.data.mongodb.core;
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
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.mongodb.core.aggregation.Aggregation;
|
|
||||||
import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
|
|
||||||
import org.springframework.data.mongodb.core.aggregation.AggregationOperationContext;
|
|
||||||
import org.springframework.data.mongodb.core.aggregation.AggregationOptions;
|
|
||||||
import org.springframework.data.mongodb.core.aggregation.CountOperation;
|
|
||||||
import org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext;
|
|
||||||
import org.springframework.data.mongodb.core.aggregation.TypedAggregation;
|
|
||||||
import org.springframework.data.mongodb.core.convert.QueryMapper;
|
|
||||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
|
||||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
|
||||||
import org.springframework.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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility methods to map {@link org.springframework.data.mongodb.core.aggregation.Aggregation} pipeline definitions and
|
|
||||||
* create type-bound {@link AggregationOperationContext}.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @author Mark Paluch
|
|
||||||
* @since 2.1
|
|
||||||
*/
|
|
||||||
@AllArgsConstructor
|
|
||||||
class AggregationUtil {
|
|
||||||
|
|
||||||
QueryMapper queryMapper;
|
|
||||||
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepare the {@link AggregationOperationContext} for a given aggregation by either returning the context itself it
|
|
||||||
* is not {@literal null}, create a {@link TypeBasedAggregationOperationContext} if the aggregation contains type
|
|
||||||
* information (is a {@link TypedAggregation}) or use the {@link Aggregation#DEFAULT_CONTEXT}.
|
|
||||||
*
|
|
||||||
* @param aggregation must not be {@literal null}.
|
|
||||||
* @param context can be {@literal null}.
|
|
||||||
* @return the root {@link AggregationOperationContext} to use.
|
|
||||||
*/
|
|
||||||
AggregationOperationContext prepareAggregationContext(Aggregation aggregation,
|
|
||||||
@Nullable AggregationOperationContext context) {
|
|
||||||
|
|
||||||
if (context != null) {
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aggregation instanceof TypedAggregation) {
|
|
||||||
return new TypeBasedAggregationOperationContext(((TypedAggregation) aggregation).getInputType(), mappingContext,
|
|
||||||
queryMapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Aggregation.DEFAULT_CONTEXT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract and map the aggregation pipeline into a {@link List} of {@link Document}.
|
|
||||||
*
|
|
||||||
* @param aggregation
|
|
||||||
* @param context
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
List<Document> createPipeline(Aggregation aggregation, AggregationOperationContext context) {
|
|
||||||
|
|
||||||
if (!ObjectUtils.nullSafeEquals(context, Aggregation.DEFAULT_CONTEXT)) {
|
|
||||||
return aggregation.toPipeline(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
return mapAggregationPipeline(aggregation.toPipeline(context));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract the command and map the aggregation pipeline.
|
|
||||||
*
|
|
||||||
* @param aggregation
|
|
||||||
* @param context
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Document createCommand(String collection, Aggregation aggregation, AggregationOperationContext context) {
|
|
||||||
|
|
||||||
Document command = aggregation.toDocument(collection, context);
|
|
||||||
|
|
||||||
if (!ObjectUtils.nullSafeEquals(context, Aggregation.DEFAULT_CONTEXT)) {
|
|
||||||
return command;
|
|
||||||
}
|
|
||||||
|
|
||||||
command.put("pipeline", mapAggregationPipeline(command.get("pipeline", List.class)));
|
|
||||||
|
|
||||||
return command;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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);
|
|
||||||
|
|
||||||
Aggregation aggregation = entityClass != null ? Aggregation.newAggregation(entityClass, pipeline)
|
|
||||||
: Aggregation.newAggregation(pipeline);
|
|
||||||
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!");
|
|
||||||
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015-2019 the original author or authors.
|
* Copyright 2015-2016 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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,14 +21,14 @@ 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
|
||||||
* 2.6 and make use of low level bulk commands on the protocol level. This interface defines a fluent API to add
|
* 2.6 and make use of low level bulk commands on the protocol level. This interface defines a fluent API to add
|
||||||
* multiple single operations or list of similar operations in sequence which can then eventually be executed by calling
|
* multiple single operations or list of similar operations in sequence which can then eventually be executed by calling
|
||||||
* {@link #execute()}.
|
* {@link #execute()}.
|
||||||
*
|
*
|
||||||
* @author Tobias Trelle
|
* @author Tobias Trelle
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @since 1.9
|
* @since 1.9
|
||||||
@@ -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,
|
||||||
@@ -49,7 +49,7 @@ public interface BulkOperations {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a single insert to the bulk operation.
|
* Add a single insert to the bulk operation.
|
||||||
*
|
*
|
||||||
* @param documents the document to insert, must not be {@literal null}.
|
* @param documents the document to insert, must not be {@literal null}.
|
||||||
* @return the current {@link BulkOperations} instance with the insert added, will never be {@literal null}.
|
* @return the current {@link BulkOperations} instance with the insert added, will never be {@literal null}.
|
||||||
*/
|
*/
|
||||||
@@ -57,7 +57,7 @@ public interface BulkOperations {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a list of inserts to the bulk operation.
|
* Add a list of inserts to the bulk operation.
|
||||||
*
|
*
|
||||||
* @param documents List of documents to insert, must not be {@literal null}.
|
* @param documents List of documents to insert, must not be {@literal null}.
|
||||||
* @return the current {@link BulkOperations} instance with the insert added, will never be {@literal null}.
|
* @return the current {@link BulkOperations} instance with the insert added, will never be {@literal null}.
|
||||||
*/
|
*/
|
||||||
@@ -65,7 +65,7 @@ public interface BulkOperations {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a single update to the bulk operation. For the update request, only the first matching document is updated.
|
* Add a single update to the bulk operation. For the update request, only the first matching document is updated.
|
||||||
*
|
*
|
||||||
* @param query update criteria, must not be {@literal null}.
|
* @param query update criteria, must not be {@literal null}.
|
||||||
* @param update {@link Update} operation to perform, must not be {@literal null}.
|
* @param update {@link Update} operation to perform, must not be {@literal null}.
|
||||||
* @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}.
|
* @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}.
|
||||||
@@ -74,7 +74,7 @@ public interface BulkOperations {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a list of updates to the bulk operation. For each update request, only the first matching document is updated.
|
* Add a list of updates to the bulk operation. For each update request, only the first matching document is updated.
|
||||||
*
|
*
|
||||||
* @param updates Update operations to perform.
|
* @param updates Update operations to perform.
|
||||||
* @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}.
|
* @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}.
|
||||||
*/
|
*/
|
||||||
@@ -82,7 +82,7 @@ public interface BulkOperations {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a single update to the bulk operation. For the update request, all matching documents are updated.
|
* Add a single update to the bulk operation. For the update request, all matching documents are updated.
|
||||||
*
|
*
|
||||||
* @param query Update criteria.
|
* @param query Update criteria.
|
||||||
* @param update Update operation to perform.
|
* @param update Update operation to perform.
|
||||||
* @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}.
|
* @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}.
|
||||||
@@ -91,7 +91,7 @@ public interface BulkOperations {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a list of updates to the bulk operation. For each update request, all matching documents are updated.
|
* Add a list of updates to the bulk operation. For each update request, all matching documents are updated.
|
||||||
*
|
*
|
||||||
* @param updates Update operations to perform.
|
* @param updates Update operations to perform.
|
||||||
* @return The bulk operation.
|
* @return The bulk operation.
|
||||||
* @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}.
|
* @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}.
|
||||||
@@ -101,7 +101,7 @@ public interface BulkOperations {
|
|||||||
/**
|
/**
|
||||||
* Add a single upsert to the bulk operation. An upsert is an update if the set of matching documents is not empty,
|
* Add a single upsert to the bulk operation. An upsert is an update if the set of matching documents is not empty,
|
||||||
* else an insert.
|
* else an insert.
|
||||||
*
|
*
|
||||||
* @param query Update criteria.
|
* @param query Update criteria.
|
||||||
* @param update Update operation to perform.
|
* @param update Update operation to perform.
|
||||||
* @return The bulk operation.
|
* @return The bulk operation.
|
||||||
@@ -112,7 +112,7 @@ public interface BulkOperations {
|
|||||||
/**
|
/**
|
||||||
* Add a list of upserts to the bulk operation. An upsert is an update if the set of matching documents is not empty,
|
* Add a list of upserts to the bulk operation. An upsert is an update if the set of matching documents is not empty,
|
||||||
* else an insert.
|
* else an insert.
|
||||||
*
|
*
|
||||||
* @param updates Updates/insert operations to perform.
|
* @param updates Updates/insert operations to perform.
|
||||||
* @return The bulk operation.
|
* @return The bulk operation.
|
||||||
* @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}.
|
* @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}.
|
||||||
@@ -121,7 +121,7 @@ public interface BulkOperations {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a single remove operation to the bulk operation.
|
* Add a single remove operation to the bulk operation.
|
||||||
*
|
*
|
||||||
* @param remove the {@link Query} to select the documents to be removed, must not be {@literal null}.
|
* @param remove the {@link Query} to select the documents to be removed, must not be {@literal null}.
|
||||||
* @return the current {@link BulkOperations} instance with the removal added, will never be {@literal null}.
|
* @return the current {@link BulkOperations} instance with the removal added, will never be {@literal null}.
|
||||||
*/
|
*/
|
||||||
@@ -129,7 +129,7 @@ public interface BulkOperations {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a list of remove operations to the bulk operation.
|
* Add a list of remove operations to the bulk operation.
|
||||||
*
|
*
|
||||||
* @param removes the remove operations to perform, must not be {@literal null}.
|
* @param removes the remove operations to perform, must not be {@literal null}.
|
||||||
* @return the current {@link BulkOperations} instance with the removal added, will never be {@literal null}.
|
* @return the current {@link BulkOperations} instance with the removal added, will never be {@literal null}.
|
||||||
*/
|
*/
|
||||||
@@ -137,9 +137,9 @@ public interface BulkOperations {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute all bulk operations using the default write concern.
|
* Execute all bulk operations using the default write concern.
|
||||||
*
|
*
|
||||||
* @return Result of the bulk operation providing counters for inserts/updates etc.
|
* @return Result of the bulk operation providing counters for inserts/updates etc.
|
||||||
* @throws org.springframework.data.mongodb.BulkOperationException if an error occurred during bulk processing.
|
* @throws {@link BulkOperationException} if an error occurred during bulk processing.
|
||||||
*/
|
*/
|
||||||
BulkWriteResult execute();
|
BulkWriteResult execute();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.data.mongodb.core;
|
|
||||||
|
|
||||||
import lombok.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
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.data.mongodb.core;
|
|
||||||
|
|
||||||
import lombok.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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,46 +1,26 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2019 the original author or authors.
|
* Copyright 2010-2011 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* 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.core;
|
package org.springframework.data.mongodb.core;
|
||||||
|
|
||||||
import org.bson.Document;
|
import com.mongodb.DBCollection;
|
||||||
import org.springframework.dao.DataAccessException;
|
import com.mongodb.MongoException;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.dao.DataAccessException;
|
||||||
|
|
||||||
import com.mongodb.MongoException;
|
public interface CollectionCallback<T> {
|
||||||
import com.mongodb.client.MongoCollection;
|
|
||||||
|
T doInCollection(DBCollection collection) throws MongoException, 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> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param collection never {@literal null}.
|
|
||||||
* @return can be {@literal null}.
|
|
||||||
* @throws MongoException
|
|
||||||
* @throws DataAccessException
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
T doInCollection(MongoCollection<Document> collection) throws MongoException, DataAccessException;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,397 +1,70 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2019 the original author or authors.
|
* Copyright 2010-2011 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* 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.core;
|
package org.springframework.data.mongodb.core;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
/**
|
||||||
|
* Provides a simple wrapper to encapsulate the variety of settings you can use when creating a collection.
|
||||||
import java.util.Optional;
|
*
|
||||||
|
* @author Thomas Risberg
|
||||||
import org.springframework.data.mongodb.core.query.Collation;
|
*/
|
||||||
import org.springframework.data.mongodb.core.schema.MongoJsonSchema;
|
public class CollectionOptions {
|
||||||
import org.springframework.data.mongodb.core.validation.Validator;
|
|
||||||
import org.springframework.data.util.Optionals;
|
private Integer maxDocuments;
|
||||||
import org.springframework.lang.Nullable;
|
|
||||||
import org.springframework.util.Assert;
|
private Integer size;
|
||||||
|
|
||||||
import com.mongodb.client.model.ValidationAction;
|
private Boolean capped;
|
||||||
import com.mongodb.client.model.ValidationLevel;
|
|
||||||
|
/**
|
||||||
/**
|
* Constructs a new <code>CollectionOptions</code> instance.
|
||||||
* Provides a simple wrapper to encapsulate the variety of settings you can use when creating a collection.
|
*
|
||||||
*
|
* @param size the collection size in bytes, this data space is preallocated
|
||||||
* @author Thomas Risberg
|
* @param maxDocuments the maximum number of documents in the collection.
|
||||||
* @author Christoph Strobl
|
* @param capped true to created a "capped" collection (fixed size with auto-FIFO behavior based on insertion order),
|
||||||
* @author Mark Paluch
|
* false otherwise.
|
||||||
* @author Andreas Zink
|
*/
|
||||||
*/
|
public CollectionOptions(Integer size, Integer maxDocuments, Boolean capped) {
|
||||||
public class CollectionOptions {
|
super();
|
||||||
|
this.maxDocuments = maxDocuments;
|
||||||
private @Nullable Long maxDocuments;
|
this.size = size;
|
||||||
private @Nullable Long size;
|
this.capped = capped;
|
||||||
private @Nullable Boolean capped;
|
}
|
||||||
private @Nullable Collation collation;
|
|
||||||
private ValidationOptions validationOptions;
|
public Integer getMaxDocuments() {
|
||||||
|
return maxDocuments;
|
||||||
/**
|
}
|
||||||
* Constructs a new <code>CollectionOptions</code> instance.
|
|
||||||
*
|
public void setMaxDocuments(Integer maxDocuments) {
|
||||||
* @param size the collection size in bytes, this data space is preallocated. Can be {@literal null}.
|
this.maxDocuments = maxDocuments;
|
||||||
* @param maxDocuments the maximum number of documents in the collection. Can be {@literal null}.
|
}
|
||||||
* @param capped true to created a "capped" collection (fixed size with auto-FIFO behavior based on insertion order),
|
|
||||||
* false otherwise. Can be {@literal null}.
|
public Integer getSize() {
|
||||||
* @deprecated since 2.0 please use {@link CollectionOptions#empty()} as entry point.
|
return size;
|
||||||
*/
|
}
|
||||||
@Deprecated
|
|
||||||
public CollectionOptions(@Nullable Long size, @Nullable Long maxDocuments, @Nullable Boolean capped) {
|
public void setSize(Integer size) {
|
||||||
this(size, maxDocuments, capped, null, ValidationOptions.none());
|
this.size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CollectionOptions(@Nullable Long size, @Nullable Long maxDocuments, @Nullable Boolean capped,
|
public Boolean getCapped() {
|
||||||
@Nullable Collation collation, ValidationOptions validationOptions) {
|
return capped;
|
||||||
|
}
|
||||||
this.maxDocuments = maxDocuments;
|
|
||||||
this.size = size;
|
public void setCapped(Boolean capped) {
|
||||||
this.capped = capped;
|
this.capped = capped;
|
||||||
this.collation = collation;
|
}
|
||||||
this.validationOptions = validationOptions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create new {@link CollectionOptions} by just providing the {@link Collation} to use.
|
|
||||||
*
|
|
||||||
* @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());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create new empty {@link CollectionOptions}.
|
|
||||||
*
|
|
||||||
* @return new {@link CollectionOptions}.
|
|
||||||
* @since 2.0
|
|
||||||
*/
|
|
||||||
public static CollectionOptions empty() {
|
|
||||||
return new CollectionOptions(null, null, null, null, ValidationOptions.none());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create new {@link CollectionOptions} with already given settings and capped set to {@literal true}. <br />
|
|
||||||
* <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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create new {@link CollectionOptions} with already given settings and {@code maxDocuments} set to given value.
|
|
||||||
*
|
|
||||||
* @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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create new {@link CollectionOptions} with already given settings and {@code size} set to given value.
|
|
||||||
*
|
|
||||||
* @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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create new {@link CollectionOptions} with already given settings and {@code collation} set to given value.
|
|
||||||
*
|
|
||||||
* @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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2019 the original author or authors.
|
* Copyright 2002-2010 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,44 +1,25 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2019 the original author or authors.
|
* Copyright 2010-2011 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
|
||||||
*
|
*
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* http://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,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* 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.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 org.springframework.dao.DataAccessException;
|
||||||
import com.mongodb.MongoException;
|
|
||||||
import com.mongodb.client.MongoDatabase;
|
public interface DbCallback<T> {
|
||||||
|
|
||||||
/**
|
T doInDB(DB db) throws MongoException, 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> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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