Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1a77b1bc56 | ||
|
|
140fb2e9ea | ||
|
|
b571c8958d | ||
|
|
8d54cae54d | ||
|
|
14a71f0498 | ||
|
|
14c265f3a1 | ||
|
|
440a289ac6 | ||
|
|
9663a2227b | ||
|
|
b134e1916d | ||
|
|
65b02f92b4 | ||
|
|
667b71e073 | ||
|
|
225dbee15f | ||
|
|
c04ceb163b | ||
|
|
711ac343fe | ||
|
|
852a4ecc59 | ||
|
|
7ab2428c64 | ||
|
|
350acf66bc | ||
|
|
ab94a94b2e | ||
|
|
4c77763cd3 | ||
|
|
f197953480 | ||
|
|
44afd4939e | ||
|
|
575917435e | ||
|
|
2db55ab0aa | ||
|
|
79602b7dbe | ||
|
|
d5d2371b9e | ||
|
|
c95e8a5748 |
2
Jenkinsfile
vendored
2
Jenkinsfile
vendored
@@ -9,7 +9,7 @@ pipeline {
|
||||
|
||||
triggers {
|
||||
pollSCM 'H/10 * * * *'
|
||||
upstream(upstreamProjects: "spring-data-commons/3.0.x", threshold: hudson.model.Result.SUCCESS)
|
||||
upstream(upstreamProjects: "spring-data-commons/main", threshold: hudson.model.Result.SUCCESS)
|
||||
}
|
||||
|
||||
options {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
image:https://spring.io/badges/spring-data-mongodb/ga.svg[Spring Data MongoDB,link=https://projects.spring.io/spring-data-mongodb#quick-start] image:https://spring.io/badges/spring-data-mongodb/snapshot.svg[Spring Data MongoDB,link=https://projects.spring.io/spring-data-mongodb#quick-start]
|
||||
image:https://spring.io/badges/spring-data-mongodb/ga.svg[Spring Data MongoDB,link=https://spring.io/projects/spring-data-mongodb#quick-start] image:https://spring.io/badges/spring-data-mongodb/snapshot.svg[Spring Data MongoDB,link=https://spring.io/projects/spring-data-mongodb#quick-start]
|
||||
|
||||
= Spring Data MongoDB image:https://jenkins.spring.io/buildStatus/icon?job=spring-data-mongodb%2Fmain&subject=Build[link=https://jenkins.spring.io/view/SpringData/job/spring-data-mongodb/] https://gitter.im/spring-projects/spring-data[image:https://badges.gitter.im/spring-projects/spring-data.svg[Gitter]]
|
||||
|
||||
The primary goal of the https://projects.spring.io/spring-data[Spring Data] project is to make it easier to build Spring-powered applications that use new data access technologies such as non-relational databases, map-reduce frameworks, and cloud based data services.
|
||||
The primary goal of the https://spring.io/projects/spring-data[Spring Data] project is to make it easier to build Spring-powered applications that use new data access technologies such as non-relational databases, map-reduce frameworks, and cloud based data services.
|
||||
|
||||
The Spring Data MongoDB project aims to provide a familiar and consistent Spring-based programming model for new datastores while retaining store-specific features and capabilities.
|
||||
The Spring Data MongoDB project provides integration with the MongoDB document database.
|
||||
|
||||
484
pom.xml
484
pom.xml
@@ -1,164 +1,326 @@
|
||||
<?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">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>4.0.0-M2</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>Spring Data MongoDB</name>
|
||||
<description>MongoDB support for Spring Data</description>
|
||||
<url>https://projects.spring.io/spring-data-mongodb</url>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.data.build</groupId>
|
||||
<artifactId>spring-data-parent</artifactId>
|
||||
<version>3.0.0-M2</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
<module>spring-data-mongodb</module>
|
||||
<module>spring-data-mongodb-distribution</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
<source.level>16</source.level>
|
||||
<project.type>multi</project.type>
|
||||
<dist.id>spring-data-mongodb</dist.id>
|
||||
<springdata.commons>3.0.0-M2</springdata.commons>
|
||||
<mongo>4.5.0</mongo>
|
||||
<mongo.reactivestreams>${mongo}</mongo.reactivestreams>
|
||||
<jmh.version>1.19</jmh.version>
|
||||
</properties>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<id>ogierke</id>
|
||||
<name>Oliver Gierke</name>
|
||||
<email>ogierke at gopivotal.com</email>
|
||||
<organization>Pivotal</organization>
|
||||
<organizationUrl>https://pivotal.io</organizationUrl>
|
||||
<roles>
|
||||
<role>Project Lead</role>
|
||||
</roles>
|
||||
<timezone>+1</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>trisberg</id>
|
||||
<name>Thomas Risberg</name>
|
||||
<email>trisberg at vmware.com</email>
|
||||
<organization>Pivotal</organization>
|
||||
<organizationUrl>https://pivotal.io</organizationUrl>
|
||||
<roles>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>-5</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>mpollack</id>
|
||||
<name>Mark Pollack</name>
|
||||
<email>mpollack at gopivotal.com</email>
|
||||
<organization>Pivotal</organization>
|
||||
<organizationUrl>https://pivotal.io</organizationUrl>
|
||||
<roles>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>-5</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>jbrisbin</id>
|
||||
<name>Jon Brisbin</name>
|
||||
<email>jbrisbin at gopivotal.com</email>
|
||||
<organization>Pivotal</organization>
|
||||
<organizationUrl>https://pivotal.io</organizationUrl>
|
||||
<roles>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>-6</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>tdarimont</id>
|
||||
<name>Thomas Darimont</name>
|
||||
<email>tdarimont at gopivotal.com</email>
|
||||
<organization>Pivotal</organization>
|
||||
<organizationUrl>https://pivotal.io</organizationUrl>
|
||||
<roles>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>+1</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>cstrobl</id>
|
||||
<name>Christoph Strobl</name>
|
||||
<email>cstrobl at gopivotal.com</email>
|
||||
<organization>Pivotal</organization>
|
||||
<organizationUrl>https://pivotal.io</organizationUrl>
|
||||
<roles>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>+1</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>mpaluch</id>
|
||||
<name>Mark Paluch</name>
|
||||
<email>mpaluch at pivotal.io</email>
|
||||
<organization>Pivotal</organization>
|
||||
<organizationUrl>https://www.pivotal.io</organizationUrl>
|
||||
<roles>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>+1</timezone>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>benchmarks</id>
|
||||
<modules>
|
||||
<module>spring-data-mongodb</module>
|
||||
<module>spring-data-mongodb-distribution</module>
|
||||
<module>spring-data-mongodb-benchmarks</module>
|
||||
</modules>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<dependencies>
|
||||
<!-- MongoDB -->
|
||||
<dependency>
|
||||
<groupId>org.mongodb</groupId>
|
||||
<artifactId>mongodb-driver-core</artifactId>
|
||||
<version>${mongo}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-libs-milestone</id>
|
||||
<url>https://repo.spring.io/libs-milestone</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>sonatype-libs-snapshot</id>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||
<releases>
|
||||
<enabled>false</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>spring-plugins-release</id>
|
||||
<url>https://repo.spring.io/plugins-release</url>
|
||||
</pluginRepository>
|
||||
<pluginRepository>
|
||||
<id>spring-libs-milestone</id>
|
||||
<url>https://repo.spring.io/libs-milestone</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.springframework.data</groupId>
|
||||
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
|
||||
<version>4.0.0-M4</version>
|
||||
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>Spring Data MongoDB</name>
|
||||
|
||||
<description>MongoDB support for Spring Data</description>
|
||||
|
||||
<url>https://spring.io/projects/spring-data-mongodb</url>
|
||||
|
||||
<parent>
|
||||
|
||||
<groupId>org.springframework.data.build</groupId>
|
||||
|
||||
<artifactId>spring-data-parent</artifactId>
|
||||
|
||||
<version>3.0.0-M4</version>
|
||||
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
||||
<module>spring-data-mongodb</module>
|
||||
|
||||
<module>spring-data-mongodb-distribution</module>
|
||||
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
|
||||
<source.level>16</source.level>
|
||||
|
||||
<project.type>multi</project.type>
|
||||
|
||||
<dist.id>spring-data-mongodb</dist.id>
|
||||
|
||||
<springdata.commons>3.0.0-M4</springdata.commons>
|
||||
|
||||
<mongo>4.6.0</mongo>
|
||||
|
||||
<mongo.reactivestreams>${mongo}</mongo.reactivestreams>
|
||||
|
||||
<jmh.version>1.19</jmh.version>
|
||||
|
||||
</properties>
|
||||
|
||||
<developers>
|
||||
|
||||
<developer>
|
||||
|
||||
<id>ogierke</id>
|
||||
|
||||
<name>Oliver Gierke</name>
|
||||
|
||||
<email>ogierke at gopivotal.com</email>
|
||||
|
||||
<organization>Pivotal</organization>
|
||||
|
||||
<organizationUrl>https://pivotal.io</organizationUrl>
|
||||
|
||||
<roles>
|
||||
|
||||
<role>Project Lead</role>
|
||||
|
||||
</roles>
|
||||
|
||||
<timezone>+1</timezone>
|
||||
|
||||
</developer>
|
||||
|
||||
<developer>
|
||||
|
||||
<id>trisberg</id>
|
||||
|
||||
<name>Thomas Risberg</name>
|
||||
|
||||
<email>trisberg at vmware.com</email>
|
||||
|
||||
<organization>Pivotal</organization>
|
||||
|
||||
<organizationUrl>https://pivotal.io</organizationUrl>
|
||||
|
||||
<roles>
|
||||
|
||||
<role>Developer</role>
|
||||
|
||||
</roles>
|
||||
|
||||
<timezone>-5</timezone>
|
||||
|
||||
</developer>
|
||||
|
||||
<developer>
|
||||
|
||||
<id>mpollack</id>
|
||||
|
||||
<name>Mark Pollack</name>
|
||||
|
||||
<email>mpollack at gopivotal.com</email>
|
||||
|
||||
<organization>Pivotal</organization>
|
||||
|
||||
<organizationUrl>https://pivotal.io</organizationUrl>
|
||||
|
||||
<roles>
|
||||
|
||||
<role>Developer</role>
|
||||
|
||||
</roles>
|
||||
|
||||
<timezone>-5</timezone>
|
||||
|
||||
</developer>
|
||||
|
||||
<developer>
|
||||
|
||||
<id>jbrisbin</id>
|
||||
|
||||
<name>Jon Brisbin</name>
|
||||
|
||||
<email>jbrisbin at gopivotal.com</email>
|
||||
|
||||
<organization>Pivotal</organization>
|
||||
|
||||
<organizationUrl>https://pivotal.io</organizationUrl>
|
||||
|
||||
<roles>
|
||||
|
||||
<role>Developer</role>
|
||||
|
||||
</roles>
|
||||
|
||||
<timezone>-6</timezone>
|
||||
|
||||
</developer>
|
||||
|
||||
<developer>
|
||||
|
||||
<id>tdarimont</id>
|
||||
|
||||
<name>Thomas Darimont</name>
|
||||
|
||||
<email>tdarimont at gopivotal.com</email>
|
||||
|
||||
<organization>Pivotal</organization>
|
||||
|
||||
<organizationUrl>https://pivotal.io</organizationUrl>
|
||||
|
||||
<roles>
|
||||
|
||||
<role>Developer</role>
|
||||
|
||||
</roles>
|
||||
|
||||
<timezone>+1</timezone>
|
||||
|
||||
</developer>
|
||||
|
||||
<developer>
|
||||
|
||||
<id>cstrobl</id>
|
||||
|
||||
<name>Christoph Strobl</name>
|
||||
|
||||
<email>cstrobl at gopivotal.com</email>
|
||||
|
||||
<organization>Pivotal</organization>
|
||||
|
||||
<organizationUrl>https://pivotal.io</organizationUrl>
|
||||
|
||||
<roles>
|
||||
|
||||
<role>Developer</role>
|
||||
|
||||
</roles>
|
||||
|
||||
<timezone>+1</timezone>
|
||||
|
||||
</developer>
|
||||
|
||||
<developer>
|
||||
|
||||
<id>mpaluch</id>
|
||||
|
||||
<name>Mark Paluch</name>
|
||||
|
||||
<email>mpaluch at pivotal.io</email>
|
||||
|
||||
<organization>Pivotal</organization>
|
||||
|
||||
<organizationUrl>https://www.pivotal.io</organizationUrl>
|
||||
|
||||
<roles>
|
||||
|
||||
<role>Developer</role>
|
||||
|
||||
</roles>
|
||||
|
||||
<timezone>+1</timezone>
|
||||
|
||||
</developer>
|
||||
|
||||
</developers>
|
||||
|
||||
<scm>
|
||||
|
||||
<connection>scm:git:https://github.com/spring-projects/spring-data-mongodb.git</connection>
|
||||
|
||||
<developerConnection>scm:git:git@github.com:spring-projects/spring-data-mongodb.git</developerConnection>
|
||||
|
||||
<url>https://github.com/spring-projects/spring-data-mongodb</url>
|
||||
|
||||
</scm>
|
||||
|
||||
<issueManagement>
|
||||
|
||||
<system>GitHub</system>
|
||||
|
||||
<url>https://github.com/spring-projects/spring-data-mongodb/issues</url>
|
||||
|
||||
</issueManagement>
|
||||
|
||||
<profiles>
|
||||
|
||||
<profile>
|
||||
|
||||
<id>benchmarks</id>
|
||||
|
||||
<modules>
|
||||
|
||||
<module>spring-data-mongodb</module>
|
||||
|
||||
<module>spring-data-mongodb-distribution</module>
|
||||
|
||||
<module>spring-data-mongodb-benchmarks</module>
|
||||
|
||||
</modules>
|
||||
|
||||
</profile>
|
||||
|
||||
</profiles>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- MongoDB -->
|
||||
|
||||
<dependency>
|
||||
|
||||
<groupId>org.mongodb</groupId>
|
||||
|
||||
<artifactId>mongodb-driver-core</artifactId>
|
||||
|
||||
<version>${mongo}</version>
|
||||
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<repositories>
|
||||
|
||||
<repository>
|
||||
|
||||
<id>spring-libs-milestone</id>
|
||||
|
||||
<url>https://repo.spring.io/libs-milestone</url>
|
||||
|
||||
<snapshots>
|
||||
|
||||
<enabled>true</enabled>
|
||||
|
||||
</snapshots>
|
||||
|
||||
</repository>
|
||||
|
||||
<repository>
|
||||
|
||||
<id>sonatype-libs-snapshot</id>
|
||||
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||
|
||||
<releases>
|
||||
|
||||
<enabled>false</enabled>
|
||||
|
||||
</releases>
|
||||
|
||||
<snapshots>
|
||||
|
||||
<enabled>true</enabled>
|
||||
|
||||
</snapshots>
|
||||
|
||||
</repository>
|
||||
|
||||
</repositories>
|
||||
|
||||
<pluginRepositories>
|
||||
|
||||
<pluginRepository>
|
||||
|
||||
<id>spring-plugins-release</id>
|
||||
|
||||
<url>https://repo.spring.io/plugins-release</url>
|
||||
|
||||
</pluginRepository>
|
||||
|
||||
<pluginRepository>
|
||||
|
||||
<id>spring-libs-milestone</id>
|
||||
|
||||
<url>https://repo.spring.io/libs-milestone</url>
|
||||
|
||||
</pluginRepository>
|
||||
|
||||
</pluginRepositories>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>4.0.0-M2</version>
|
||||
<version>4.0.0-M4</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -14,13 +15,18 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>4.0.0-M2</version>
|
||||
<version>4.0.0-M4</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<project.root>${basedir}/..</project.root>
|
||||
<dist.key>SDMONGO</dist.key>
|
||||
|
||||
<!-- Observability -->
|
||||
<micrometer-docs-generator.inputPath>${maven.multiModuleProjectDirectory}/spring-data-mongodb/</micrometer-docs-generator.inputPath>
|
||||
<micrometer-docs-generator.inclusionPattern>.*</micrometer-docs-generator.inclusionPattern>
|
||||
<micrometer-docs-generator.outputPath>${maven.multiModuleProjectDirectory}/target/</micrometer-docs-generator.outputPath>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
@@ -29,12 +35,63 @@
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>generate-metrics-metadata</id>
|
||||
<phase>prepare-package</phase>
|
||||
<goals>
|
||||
<goal>java</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<mainClass>io.micrometer.docs.metrics.DocsFromSources
|
||||
</mainClass>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>generate-tracing-metadata</id>
|
||||
<phase>prepare-package</phase>
|
||||
<goals>
|
||||
<goal>java</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<mainClass>io.micrometer.docs.spans.DocsFromSources
|
||||
</mainClass>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.micrometer</groupId>
|
||||
<artifactId>micrometer-docs-generator-spans</artifactId>
|
||||
<version>${micrometer-docs-generator}</version>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.micrometer</groupId>
|
||||
<artifactId>micrometer-docs-generator-metrics</artifactId>
|
||||
<version>${micrometer-docs-generator}</version>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<configuration>
|
||||
<includePluginDependencies>true</includePluginDependencies>
|
||||
<arguments>
|
||||
<argument>${micrometer-docs-generator.inputPath}</argument>
|
||||
<argument>${micrometer-docs-generator.inclusionPattern}</argument>
|
||||
<argument>${micrometer-docs-generator.outputPath}</argument>
|
||||
</arguments>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.asciidoctor</groupId>
|
||||
<artifactId>asciidoctor-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<attributes>
|
||||
<mongo-reactivestreams>${mongo.reactivestreams}</mongo-reactivestreams>
|
||||
<mongo-reactivestreams>${mongo.reactivestreams}
|
||||
</mongo-reactivestreams>
|
||||
<reactor>${reactor}</reactor>
|
||||
</attributes>
|
||||
</configuration>
|
||||
|
||||
@@ -1,361 +1,391 @@
|
||||
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>spring-data-mongodb</artifactId>
|
||||
<artifactId>spring-data-mongodb</artifactId>
|
||||
|
||||
<name>Spring Data MongoDB - Core</name>
|
||||
<description>MongoDB support for Spring Data</description>
|
||||
<name>Spring Data MongoDB - Core</name>
|
||||
<description>MongoDB support for Spring Data</description>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>4.0.0-M2</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>4.0.0-M4</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<objenesis>1.3</objenesis>
|
||||
<equalsverifier>1.7.8</equalsverifier>
|
||||
<java-module-name>spring.data.mongodb</java-module-name>
|
||||
<project.root>${basedir}/..</project.root>
|
||||
<multithreadedtc>1.01</multithreadedtc>
|
||||
</properties>
|
||||
<properties>
|
||||
<objenesis>1.3</objenesis>
|
||||
<equalsverifier>1.7.8</equalsverifier>
|
||||
<java-module-name>spring.data.mongodb</java-module-name>
|
||||
<project.root>${basedir}/..</project.root>
|
||||
<multithreadedtc>1.01</multithreadedtc>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependencies>
|
||||
|
||||
<!-- Spring -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-expression</artifactId>
|
||||
</dependency>
|
||||
<!-- Spring -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-expression</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Data -->
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-data-commons</artifactId>
|
||||
<version>${springdata.commons}</version>
|
||||
</dependency>
|
||||
<!-- Spring Data -->
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-data-commons</artifactId>
|
||||
<version>${springdata.commons}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.querydsl</groupId>
|
||||
<artifactId>querydsl-mongodb</artifactId>
|
||||
<version>${querydsl}</version>
|
||||
<optional>true</optional>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.mongodb</groupId>
|
||||
<artifactId>mongo-java-driver</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.querydsl</groupId>
|
||||
<artifactId>querydsl-mongodb</artifactId>
|
||||
<version>${querydsl}</version>
|
||||
<optional>true</optional>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.mongodb</groupId>
|
||||
<artifactId>mongo-java-driver</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.querydsl</groupId>
|
||||
<artifactId>querydsl-apt</artifactId>
|
||||
<version>${querydsl}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.querydsl</groupId>
|
||||
<artifactId>querydsl-apt</artifactId>
|
||||
<version>${querydsl}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>jsr250-api</artifactId>
|
||||
<version>1.0</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>jsr250-api</artifactId>
|
||||
<version>1.0</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.code.findbugs</groupId>
|
||||
<artifactId>jsr305</artifactId>
|
||||
<version>3.0.2</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.findbugs</groupId>
|
||||
<artifactId>jsr305</artifactId>
|
||||
<version>3.0.2</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- reactive -->
|
||||
<!-- reactive -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mongodb</groupId>
|
||||
<artifactId>mongodb-driver-sync</artifactId>
|
||||
<version>${mongo}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mongodb</groupId>
|
||||
<artifactId>mongodb-driver-sync</artifactId>
|
||||
<version>${mongo}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<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-reactivestreams</artifactId>
|
||||
<version>${mongo.reactivestreams}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.projectreactor</groupId>
|
||||
<artifactId>reactor-core</artifactId>
|
||||
<optional>true</optional>
|
||||
</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.projectreactor</groupId>
|
||||
<artifactId>reactor-test</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.reactivex.rxjava3</groupId>
|
||||
<artifactId>rxjava</artifactId>
|
||||
<version>${rxjava3}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.reactivex.rxjava3</groupId>
|
||||
<artifactId>rxjava</artifactId>
|
||||
<version>${rxjava3}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- CDI -->
|
||||
<!-- Dependency order required to build against CDI 1.0 and test with CDI 2.0 -->
|
||||
<!-- CDI -->
|
||||
<!-- Dependency order required to build against CDI 1.0 and test with CDI 2.0 -->
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.interceptor</groupId>
|
||||
<artifactId>javax.interceptor-api</artifactId>
|
||||
<version>1.2.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>
|
||||
<groupId>jakarta.enterprise</groupId>
|
||||
<artifactId>jakarta.enterprise.cdi-api</artifactId>
|
||||
<version>${cdi}</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.enterprise</groupId>
|
||||
<artifactId>jakarta.enterprise.cdi-api</artifactId>
|
||||
<version>${cdi}</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>jakarta.annotation</groupId>
|
||||
<artifactId>jakarta.annotation-api</artifactId>
|
||||
<version>${jakarta-annotation-api}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.annotation</groupId>
|
||||
<artifactId>jakarta.annotation-api</artifactId>
|
||||
<version>${jakarta-annotation-api}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.openwebbeans</groupId>
|
||||
<artifactId>openwebbeans-se</artifactId>
|
||||
<classifier>jakarta</classifier>
|
||||
<version>${webbeans}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.openwebbeans</groupId>
|
||||
<artifactId>openwebbeans-se</artifactId>
|
||||
<classifier>jakarta</classifier>
|
||||
<version>${webbeans}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.openwebbeans</groupId>
|
||||
<artifactId>openwebbeans-spi</artifactId>
|
||||
<classifier>jakarta</classifier>
|
||||
<version>${webbeans}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.openwebbeans</groupId>
|
||||
<artifactId>openwebbeans-spi</artifactId>
|
||||
<classifier>jakarta</classifier>
|
||||
<version>${webbeans}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.openwebbeans</groupId>
|
||||
<artifactId>openwebbeans-impl</artifactId>
|
||||
<classifier>jakarta</classifier>
|
||||
<version>${webbeans}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.openwebbeans</groupId>
|
||||
<artifactId>openwebbeans-impl</artifactId>
|
||||
<classifier>jakarta</classifier>
|
||||
<version>${webbeans}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- JSR 303 Validation -->
|
||||
<dependency>
|
||||
<groupId>jakarta.validation</groupId>
|
||||
<artifactId>jakarta.validation-api</artifactId>
|
||||
<version>${validation}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<!-- JSR 303 Validation -->
|
||||
<dependency>
|
||||
<groupId>jakarta.validation</groupId>
|
||||
<artifactId>jakarta.validation-api</artifactId>
|
||||
<version>${validation}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.objenesis</groupId>
|
||||
<artifactId>objenesis</artifactId>
|
||||
<version>${objenesis}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.objenesis</groupId>
|
||||
<artifactId>objenesis</artifactId>
|
||||
<version>${objenesis}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
<version>7.0.1.Final</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.micrometer</groupId>
|
||||
<artifactId>micrometer-observation</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>jakarta.el</groupId>
|
||||
<artifactId>jakarta.el-api</artifactId>
|
||||
<version>4.0.0</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.micrometer</groupId>
|
||||
<artifactId>micrometer-tracing-api</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.glassfish</groupId>
|
||||
<artifactId>jakarta.el</artifactId>
|
||||
<version>4.0.2</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate.validator</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
<version>7.0.1.Final</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.el</groupId>
|
||||
<artifactId>jakarta.el-api</artifactId>
|
||||
<version>4.0.0</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>nl.jqno.equalsverifier</groupId>
|
||||
<artifactId>equalsverifier</artifactId>
|
||||
<version>${equalsverifier}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish</groupId>
|
||||
<artifactId>jakarta.el</artifactId>
|
||||
<version>4.0.2</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>de.schauderhaft.degraph</groupId>
|
||||
<artifactId>degraph-check</artifactId>
|
||||
<version>0.1.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>nl.jqno.equalsverifier</groupId>
|
||||
<artifactId>equalsverifier</artifactId>
|
||||
<version>${equalsverifier}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>edu.umd.cs.mtc</groupId>
|
||||
<artifactId>multithreadedtc</artifactId>
|
||||
<version>${multithreadedtc}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit-pioneer</groupId>
|
||||
<artifactId>junit-pioneer</artifactId>
|
||||
<version>0.5.3</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>de.schauderhaft.degraph</groupId>
|
||||
<artifactId>degraph-check</artifactId>
|
||||
<version>0.1.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>jakarta.transaction</groupId>
|
||||
<artifactId>jakarta.transaction-api</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>edu.umd.cs.mtc</groupId>
|
||||
<artifactId>multithreadedtc</artifactId>
|
||||
<version>${multithreadedtc}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Kotlin extension -->
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-stdlib</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit-pioneer</groupId>
|
||||
<artifactId>junit-pioneer</artifactId>
|
||||
<version>0.5.3</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-reflect</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.transaction</groupId>
|
||||
<artifactId>jakarta.transaction-api</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlinx</groupId>
|
||||
<artifactId>kotlinx-coroutines-core</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<!-- Kotlin extension -->
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-stdlib</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlinx</groupId>
|
||||
<artifactId>kotlinx-coroutines-reactor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-reflect</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.mockk</groupId>
|
||||
<artifactId>mockk</artifactId>
|
||||
<version>${mockk}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlinx</groupId>
|
||||
<artifactId>kotlinx-coroutines-core</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- jMolecules -->
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlinx</groupId>
|
||||
<artifactId>kotlinx-coroutines-reactor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jmolecules</groupId>
|
||||
<artifactId>jmolecules-ddd</artifactId>
|
||||
<version>${jmolecules}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.mockk</groupId>
|
||||
<artifactId>mockk</artifactId>
|
||||
<version>${mockk}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<dependency>
|
||||
<groupId>io.micrometer</groupId>
|
||||
<artifactId>micrometer-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.micrometer</groupId>
|
||||
<artifactId>micrometer-tracing-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<build>
|
||||
<dependency>
|
||||
<groupId>io.micrometer</groupId>
|
||||
<artifactId>micrometer-tracing-integration-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<plugins>
|
||||
<!-- jMolecules -->
|
||||
|
||||
<plugin>
|
||||
<groupId>com.mysema.maven</groupId>
|
||||
<artifactId>apt-maven-plugin</artifactId>
|
||||
<version>${apt}</version>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.querydsl</groupId>
|
||||
<artifactId>querydsl-apt</artifactId>
|
||||
<version>${querydsl}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>generate-test-sources</phase>
|
||||
<goals>
|
||||
<goal>test-process</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>target/generated-test-sources</outputDirectory>
|
||||
<processor>org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor</processor>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<dependency>
|
||||
<groupId>org.jmolecules</groupId>
|
||||
<artifactId>jmolecules-ddd</artifactId>
|
||||
<version>${jmolecules}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<useSystemClassLoader>false</useSystemClassLoader>
|
||||
<useFile>false</useFile>
|
||||
<includes>
|
||||
<include>**/*Tests.java</include>
|
||||
</includes>
|
||||
<excludes>
|
||||
<exclude>**/PerformanceTests.java</exclude>
|
||||
<exclude>**/ReactivePerformanceTests.java</exclude>
|
||||
</excludes>
|
||||
<systemPropertyVariables>
|
||||
<java.util.logging.config.file>src/test/resources/logging.properties</java.util.logging.config.file>
|
||||
<reactor.trace.cancel>true</reactor.trace.cancel>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</dependencies>
|
||||
|
||||
</plugins>
|
||||
<build>
|
||||
|
||||
</build>
|
||||
<plugins>
|
||||
|
||||
<plugin>
|
||||
<groupId>com.mysema.maven</groupId>
|
||||
<artifactId>apt-maven-plugin</artifactId>
|
||||
<version>${apt}</version>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.querydsl</groupId>
|
||||
<artifactId>querydsl-apt</artifactId>
|
||||
<version>${querydsl}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>generate-test-sources</phase>
|
||||
<goals>
|
||||
<goal>test-process</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>target/generated-test-sources</outputDirectory>
|
||||
<processor>org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor</processor>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<useSystemClassLoader>false</useSystemClassLoader>
|
||||
<useFile>false</useFile>
|
||||
<includes>
|
||||
<include>**/*Tests.java</include>
|
||||
</includes>
|
||||
<excludes>
|
||||
<exclude>**/PerformanceTests.java</exclude>
|
||||
<exclude>**/ReactivePerformanceTests.java</exclude>
|
||||
</excludes>
|
||||
<systemPropertyVariables>
|
||||
<java.util.logging.config.file>src/test/resources/logging.properties</java.util.logging.config.file>
|
||||
<reactor.trace.cancel>true</reactor.trace.cancel>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
|
||||
</build>
|
||||
</project>
|
||||
|
||||
@@ -35,6 +35,7 @@ import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.core.CollectionFactory;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.data.annotation.Reference;
|
||||
import org.springframework.data.convert.CustomConversions;
|
||||
@@ -935,9 +936,10 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
TypeInformation<?> valueType = ClassTypeInformation.from(obj.getClass());
|
||||
TypeInformation<?> type = prop.getTypeInformation();
|
||||
|
||||
if (conversions.hasPropertyValueConverter(prop)) {
|
||||
if (conversions.hasValueConverter(prop)) {
|
||||
accessor.put(prop,
|
||||
conversions.getPropertyValueConverter(prop).write(obj, new MongoConversionContext(prop, this)));
|
||||
conversions.getPropertyValueConversions().getValueConverter(prop)
|
||||
.write(obj, new MongoConversionContext(prop, this)));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1271,9 +1273,10 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
private void writeSimpleInternal(@Nullable Object value, Bson bson, MongoPersistentProperty property) {
|
||||
DocumentAccessor accessor = new DocumentAccessor(bson);
|
||||
|
||||
if (conversions.hasPropertyValueConverter(property)) {
|
||||
if (conversions.hasValueConverter(property)) {
|
||||
accessor.put(property,
|
||||
conversions.getPropertyValueConverter(property).write(value, new MongoConversionContext(property, this)));
|
||||
conversions.getPropertyValueConversions().getValueConverter(property)
|
||||
.write(value, new MongoConversionContext(property, this)));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1918,8 +1921,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
return null;
|
||||
}
|
||||
|
||||
if (context.conversions.hasPropertyValueConverter(property)) {
|
||||
return (T) context.conversions.getPropertyValueConverter(property).read(value,
|
||||
if (context.conversions.hasValueConverter(property)) {
|
||||
return (T) context.conversions.getPropertyValueConversions().getValueConverter(property).read(value,
|
||||
new MongoConversionContext(property, context.sourceConverter));
|
||||
}
|
||||
|
||||
@@ -2131,6 +2134,11 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
public org.springframework.data.util.TypeInformation<? extends S> specialize(ClassTypeInformation type) {
|
||||
return delegate.specialize(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeDescriptor toTypeDescriptor() {
|
||||
return delegate.toTypeDescriptor();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -156,7 +156,8 @@ public class MongoCustomConversions extends org.springframework.data.convert.Cus
|
||||
private boolean useNativeDriverJavaTimeCodecs = false;
|
||||
private final List<Object> customConverters = new ArrayList<>();
|
||||
|
||||
private PropertyValueConversions propertyValueConversions = new SimplePropertyValueConversions();
|
||||
private final PropertyValueConversions internalValueConversion = PropertyValueConversions.simple(it -> {});
|
||||
private PropertyValueConversions propertyValueConversions = internalValueConversion;
|
||||
|
||||
/**
|
||||
* Create a {@link MongoConverterConfigurationAdapter} using the provided {@code converters} and our own codecs for
|
||||
@@ -177,7 +178,7 @@ public class MongoCustomConversions extends org.springframework.data.convert.Cus
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether or not to use the native MongoDB Java Driver {@link org.bson.codecs.Codec codes} for
|
||||
* Set whether to or not to use the native MongoDB Java Driver {@link org.bson.codecs.Codec codes} for
|
||||
* {@link org.bson.codecs.jsr310.LocalDateCodec LocalDate}, {@link org.bson.codecs.jsr310.LocalTimeCodec LocalTime}
|
||||
* and {@link org.bson.codecs.jsr310.LocalDateTimeCodec LocalDateTime} using a {@link ZoneOffset#UTC}.
|
||||
*
|
||||
@@ -317,7 +318,7 @@ public class MongoCustomConversions extends org.springframework.data.convert.Cus
|
||||
PropertyValueConversions valueConversions() {
|
||||
|
||||
if (this.propertyValueConversions == null) {
|
||||
this.propertyValueConversions = new SimplePropertyValueConversions();
|
||||
this.propertyValueConversions = internalValueConversion;
|
||||
}
|
||||
|
||||
return this.propertyValueConversions;
|
||||
@@ -325,6 +326,11 @@ public class MongoCustomConversions extends org.springframework.data.convert.Cus
|
||||
|
||||
ConverterConfiguration createConverterConfiguration() {
|
||||
|
||||
if (hasDefaultPropertyValueConversions()
|
||||
&& propertyValueConversions instanceof SimplePropertyValueConversions svc) {
|
||||
svc.init();
|
||||
}
|
||||
|
||||
if (!useNativeDriverJavaTimeCodecs) {
|
||||
return new ConverterConfiguration(STORE_CONVERSIONS, this.customConverters, convertiblePair -> true,
|
||||
this.propertyValueConversions);
|
||||
@@ -381,5 +387,9 @@ public class MongoCustomConversions extends org.springframework.data.convert.Cus
|
||||
return DateToUtcLocalDateTimeConverter.INSTANCE.convert(source).toLocalDate();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasDefaultPropertyValueConversions() {
|
||||
return propertyValueConversions == internalValueConversion;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -432,8 +432,9 @@ public class QueryMapper {
|
||||
|
||||
Object value = applyFieldTargetTypeHintToValue(documentField, sourceValue);
|
||||
|
||||
if(documentField.getProperty() != null && converter.getCustomConversions().hasPropertyValueConverter(documentField.getProperty())) {
|
||||
return converter.getCustomConversions().getPropertyValueConverter(documentField.getProperty()).write(value, new MongoConversionContext(documentField.getProperty(), converter));
|
||||
if(documentField.getProperty() != null && converter.getCustomConversions().hasValueConverter(documentField.getProperty())) {
|
||||
return converter.getCustomConversions().getPropertyValueConversions().getValueConverter(documentField.getProperty())
|
||||
.write(value, new MongoConversionContext(documentField.getProperty(), converter));
|
||||
}
|
||||
|
||||
if (documentField.isIdField() && !documentField.isAssociation()) {
|
||||
|
||||
@@ -122,9 +122,10 @@ public class Query {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set number of documents to skip before returning results.
|
||||
* Set number of documents to skip before returning results. Use {@literal zero} or a {@literal negative} value to
|
||||
* avoid skipping.
|
||||
*
|
||||
* @param skip
|
||||
* @param skip number of documents to skip. Use {@literal zero} or a {@literal negative} value to avoid skipping.
|
||||
* @return this.
|
||||
*/
|
||||
public Query skip(long skip) {
|
||||
@@ -133,9 +134,10 @@ public class Query {
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the number of returned documents to {@code limit}.
|
||||
* Limit the number of returned documents to {@code limit}. A {@literal zero} or {@literal negative} value is
|
||||
* considered as unlimited.
|
||||
*
|
||||
* @param limit
|
||||
* @param limit number of documents to return. Use {@literal zero} or {@literal negative} for unlimited.
|
||||
* @return this.
|
||||
*/
|
||||
public Query limit(int limit) {
|
||||
@@ -312,7 +314,7 @@ public class Query {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of documents to skip.
|
||||
* Get the number of documents to skip. {@literal Zero} or a {@literal negative} value indicates no skip.
|
||||
*
|
||||
* @return number of documents to skip
|
||||
*/
|
||||
@@ -321,7 +323,8 @@ public class Query {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the maximum number of documents to be return.
|
||||
* Get the maximum number of documents to be return. {@literal Zero} or a {@literal negative} value indicates no
|
||||
* limit.
|
||||
*
|
||||
* @return number of documents to return.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author 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.observability;
|
||||
|
||||
import io.micrometer.common.KeyValue;
|
||||
import io.micrometer.common.KeyValues;
|
||||
|
||||
import org.springframework.data.mongodb.observability.MongoObservation.HighCardinalityCommandKeyNames;
|
||||
import org.springframework.data.mongodb.observability.MongoObservation.LowCardinalityCommandKeyNames;
|
||||
|
||||
import com.mongodb.connection.ConnectionDescription;
|
||||
import com.mongodb.connection.ConnectionId;
|
||||
import com.mongodb.event.CommandStartedEvent;
|
||||
|
||||
/**
|
||||
* Default {@link MongoHandlerKeyValuesProvider} implementation.
|
||||
*
|
||||
* @author Greg Turnquist
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public class DefaultMongoHandlerKeyValuesProvider implements MongoHandlerKeyValuesProvider {
|
||||
|
||||
@Override
|
||||
public KeyValues getLowCardinalityKeyValues(MongoHandlerContext context) {
|
||||
|
||||
KeyValues keyValues = KeyValues.empty();
|
||||
|
||||
if (context.getCollectionName() != null) {
|
||||
keyValues = keyValues
|
||||
.and(KeyValue.of(LowCardinalityCommandKeyNames.MONGODB_COLLECTION.getKeyName(), context.getCollectionName()));
|
||||
}
|
||||
|
||||
KeyValue connectionTag = connectionTag(context.getCommandStartedEvent());
|
||||
if (connectionTag != null) {
|
||||
keyValues = keyValues.and(connectionTag);
|
||||
}
|
||||
|
||||
return keyValues;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyValues getHighCardinalityKeyValues(MongoHandlerContext context) {
|
||||
|
||||
return KeyValues.of(KeyValue.of(HighCardinalityCommandKeyNames.MONGODB_COMMAND.getKeyName(),
|
||||
context.getCommandStartedEvent().getCommandName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract connection details for a MongoDB connection into a {@link KeyValue}.
|
||||
*
|
||||
* @param event
|
||||
* @return
|
||||
*/
|
||||
private static KeyValue connectionTag(CommandStartedEvent event) {
|
||||
|
||||
ConnectionDescription connectionDescription = event.getConnectionDescription();
|
||||
|
||||
if (connectionDescription != null) {
|
||||
|
||||
ConnectionId connectionId = connectionDescription.getConnectionId();
|
||||
if (connectionId != null) {
|
||||
return KeyValue.of(LowCardinalityCommandKeyNames.MONGODB_CLUSTER_ID.getKeyName(),
|
||||
connectionId.getServerId().getClusterId().getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author 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.observability;
|
||||
|
||||
import io.micrometer.observation.Observation;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bson.BsonDocument;
|
||||
import org.bson.BsonValue;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import com.mongodb.RequestContext;
|
||||
import com.mongodb.event.CommandFailedEvent;
|
||||
import com.mongodb.event.CommandStartedEvent;
|
||||
import com.mongodb.event.CommandSucceededEvent;
|
||||
|
||||
/**
|
||||
* A {@link Observation.Context} that contains MongoDB events.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @author Greg Turnquist
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public class MongoHandlerContext extends Observation.Context {
|
||||
|
||||
/**
|
||||
* @see https://docs.mongodb.com/manual/reference/command for the command reference
|
||||
*/
|
||||
private static final Set<String> COMMANDS_WITH_COLLECTION_NAME = new LinkedHashSet<>(
|
||||
Arrays.asList("aggregate", "count", "distinct", "mapReduce", "geoSearch", "delete", "find", "findAndModify",
|
||||
"insert", "update", "collMod", "compact", "convertToCapped", "create", "createIndexes", "drop", "dropIndexes",
|
||||
"killCursors", "listIndexes", "reIndex"));
|
||||
|
||||
private final CommandStartedEvent commandStartedEvent;
|
||||
private final RequestContext requestContext;
|
||||
private final String collectionName;
|
||||
|
||||
private CommandSucceededEvent commandSucceededEvent;
|
||||
private CommandFailedEvent commandFailedEvent;
|
||||
|
||||
public MongoHandlerContext(CommandStartedEvent commandStartedEvent, RequestContext requestContext) {
|
||||
|
||||
this.commandStartedEvent = commandStartedEvent;
|
||||
this.requestContext = requestContext;
|
||||
this.collectionName = getCollectionName(commandStartedEvent);
|
||||
}
|
||||
|
||||
public CommandStartedEvent getCommandStartedEvent() {
|
||||
return this.commandStartedEvent;
|
||||
}
|
||||
|
||||
public RequestContext getRequestContext() {
|
||||
return this.requestContext;
|
||||
}
|
||||
|
||||
public String getCollectionName() {
|
||||
return this.collectionName;
|
||||
}
|
||||
|
||||
public String getContextualName() {
|
||||
|
||||
if (this.collectionName == null) {
|
||||
return this.commandStartedEvent.getCommandName();
|
||||
}
|
||||
|
||||
return this.commandStartedEvent.getCommandName() + " " + this.collectionName;
|
||||
}
|
||||
|
||||
public void setCommandSucceededEvent(CommandSucceededEvent commandSucceededEvent) {
|
||||
this.commandSucceededEvent = commandSucceededEvent;
|
||||
}
|
||||
|
||||
public void setCommandFailedEvent(CommandFailedEvent commandFailedEvent) {
|
||||
this.commandFailedEvent = commandFailedEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the command name into a collection name;
|
||||
*
|
||||
* @param event the {@link CommandStartedEvent}
|
||||
* @return the name of the collection based on the command
|
||||
*/
|
||||
@Nullable
|
||||
private static String getCollectionName(CommandStartedEvent event) {
|
||||
|
||||
String commandName = event.getCommandName();
|
||||
BsonDocument command = event.getCommand();
|
||||
|
||||
if (COMMANDS_WITH_COLLECTION_NAME.contains(commandName)) {
|
||||
|
||||
String collectionName = getNonEmptyBsonString(command.get(commandName));
|
||||
|
||||
if (collectionName != null) {
|
||||
return collectionName;
|
||||
}
|
||||
}
|
||||
|
||||
// Some other commands, like getMore, have a field like {"collection": collectionName}.
|
||||
return getNonEmptyBsonString(command.get("collection"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to convert {@link BsonValue} into a plain string.
|
||||
*
|
||||
* @return trimmed string from {@code bsonValue} or null if the trimmed string was empty or the value wasn't a string
|
||||
*/
|
||||
@Nullable
|
||||
private static String getNonEmptyBsonString(BsonValue bsonValue) {
|
||||
|
||||
if (bsonValue == null || !bsonValue.isString()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String stringValue = bsonValue.asString().getValue().trim();
|
||||
|
||||
return stringValue.isEmpty() ? null : stringValue;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author 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.observability;
|
||||
|
||||
import io.micrometer.observation.Observation;
|
||||
|
||||
/**
|
||||
* {@link Observation.KeyValuesProvider} for {@link MongoHandlerContext}.
|
||||
*
|
||||
* @author Greg Turnquist
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public interface MongoHandlerKeyValuesProvider extends Observation.KeyValuesProvider<MongoHandlerContext> {
|
||||
|
||||
@Override
|
||||
default boolean supportsContext(Observation.Context context) {
|
||||
return context instanceof MongoHandlerContext;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author 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.observability;
|
||||
|
||||
import io.micrometer.common.docs.KeyName;
|
||||
import io.micrometer.observation.docs.DocumentedObservation;
|
||||
|
||||
/**
|
||||
* A MongoDB-based {@link io.micrometer.observation.Observation}.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @author Greg Turnquist
|
||||
* @since 4.0.0
|
||||
*/
|
||||
enum MongoObservation implements DocumentedObservation {
|
||||
|
||||
/**
|
||||
* Timer created around a MongoDB command execution.
|
||||
*/
|
||||
MONGODB_COMMAND_OBSERVATION {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "spring.data.mongodb.command";
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyName[] getLowCardinalityKeyNames() {
|
||||
return LowCardinalityCommandKeyNames.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyName[] getHighCardinalityKeyNames() {
|
||||
return HighCardinalityCommandKeyNames.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPrefix() {
|
||||
return "spring.data.mongodb";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Enums related to low cardinality key names for MongoDB commands.
|
||||
*/
|
||||
enum LowCardinalityCommandKeyNames implements KeyName {
|
||||
|
||||
/**
|
||||
* MongoDB collection name.
|
||||
*/
|
||||
MONGODB_COLLECTION {
|
||||
@Override
|
||||
public String getKeyName() {
|
||||
return "spring.data.mongodb.collection";
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* MongoDB cluster identifier.
|
||||
*/
|
||||
MONGODB_CLUSTER_ID {
|
||||
@Override
|
||||
public String getKeyName() {
|
||||
return "spring.data.mongodb.cluster_id";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enums related to high cardinality key names for MongoDB commands.
|
||||
*/
|
||||
enum HighCardinalityCommandKeyNames implements KeyName {
|
||||
|
||||
/**
|
||||
* MongoDB command value.
|
||||
*/
|
||||
MONGODB_COMMAND {
|
||||
@Override
|
||||
public String getKeyName() {
|
||||
return "spring.data.mongodb.command";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author 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.observability;
|
||||
|
||||
import io.micrometer.observation.Observation;
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import com.mongodb.RequestContext;
|
||||
import com.mongodb.event.CommandFailedEvent;
|
||||
import com.mongodb.event.CommandListener;
|
||||
import com.mongodb.event.CommandStartedEvent;
|
||||
import com.mongodb.event.CommandSucceededEvent;
|
||||
|
||||
/**
|
||||
* Implement MongoDB's {@link CommandListener} using Micrometer's {@link Observation} API.
|
||||
*
|
||||
* @see https://github.com/openzipkin/brave/blob/release-5.13.0/instrumentation/mongodb/src/main/java/brave/mongodb/TraceMongoCommandListener.java
|
||||
* @author OpenZipkin Brave Authors
|
||||
* @author Marcin Grzejszczak
|
||||
* @author Greg Turnquist
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public final class MongoObservationCommandListener
|
||||
implements CommandListener, Observation.KeyValuesProviderAware<MongoHandlerKeyValuesProvider> {
|
||||
|
||||
private static final Log log = LogFactory.getLog(MongoObservationCommandListener.class);
|
||||
|
||||
private final ObservationRegistry observationRegistry;
|
||||
|
||||
private MongoHandlerKeyValuesProvider keyValuesProvider;
|
||||
|
||||
public MongoObservationCommandListener(ObservationRegistry observationRegistry) {
|
||||
|
||||
this.observationRegistry = observationRegistry;
|
||||
this.keyValuesProvider = new DefaultMongoHandlerKeyValuesProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commandStarted(CommandStartedEvent event) {
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Instrumenting the command started event");
|
||||
}
|
||||
|
||||
String databaseName = event.getDatabaseName();
|
||||
|
||||
if ("admin".equals(databaseName)) {
|
||||
return; // don't instrument commands like "endSessions"
|
||||
}
|
||||
|
||||
RequestContext requestContext = event.getRequestContext();
|
||||
|
||||
if (requestContext == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Observation parent = observationFromContext(requestContext);
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Found the following observation passed from the mongo context [" + parent + "]");
|
||||
}
|
||||
|
||||
if (parent == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
setupObservability(event, requestContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commandSucceeded(CommandSucceededEvent event) {
|
||||
|
||||
if (event.getRequestContext() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Observation observation = event.getRequestContext().getOrDefault(Observation.class, null);
|
||||
if (observation == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
MongoHandlerContext context = event.getRequestContext().get(MongoHandlerContext.class);
|
||||
context.setCommandSucceededEvent(event);
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Command succeeded - will stop observation [" + observation + "]");
|
||||
}
|
||||
|
||||
observation.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commandFailed(CommandFailedEvent event) {
|
||||
|
||||
if (event.getRequestContext() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Observation observation = event.getRequestContext().getOrDefault(Observation.class, null);
|
||||
if (observation == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
MongoHandlerContext context = event.getRequestContext().get(MongoHandlerContext.class);
|
||||
context.setCommandFailedEvent(event);
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Command failed - will stop observation [" + observation + "]");
|
||||
}
|
||||
|
||||
observation.error(event.getThrowable());
|
||||
observation.stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the {@link Observation} from MongoDB's {@link RequestContext}.
|
||||
*
|
||||
* @param context
|
||||
* @return
|
||||
*/
|
||||
private static Observation observationFromContext(RequestContext context) {
|
||||
|
||||
Observation observation = context.getOrDefault(Observation.class, null);
|
||||
|
||||
if (observation != null) {
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Found a observation in mongo context [" + observation + "]");
|
||||
}
|
||||
return observation;
|
||||
}
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("No observation was found - will not create any child spans");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void setupObservability(CommandStartedEvent event, RequestContext requestContext) {
|
||||
|
||||
MongoHandlerContext observationContext = new MongoHandlerContext(event, requestContext);
|
||||
|
||||
Observation observation = MongoObservation.MONGODB_COMMAND_OBSERVATION
|
||||
.observation(this.observationRegistry, observationContext) //
|
||||
.contextualName(observationContext.getContextualName()) //
|
||||
.keyValuesProvider(this.keyValuesProvider) //
|
||||
.start();
|
||||
|
||||
requestContext.put(Observation.class, observation);
|
||||
requestContext.put(MongoHandlerContext.class, observationContext);
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(
|
||||
"Created a child observation [" + observation + "] for mongo instrumentation and put it in mongo context");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setKeyValuesProvider(MongoHandlerKeyValuesProvider mongoHandlerKeyValuesProvider) {
|
||||
this.keyValuesProvider = mongoHandlerKeyValuesProvider;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author 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.observability;
|
||||
|
||||
import io.micrometer.observation.Observation;
|
||||
import io.micrometer.tracing.Span;
|
||||
import io.micrometer.tracing.Tracer;
|
||||
import io.micrometer.tracing.handler.TracingObservationHandler;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import com.mongodb.MongoSocketException;
|
||||
import com.mongodb.connection.ConnectionDescription;
|
||||
import com.mongodb.event.CommandStartedEvent;
|
||||
|
||||
/**
|
||||
* A {@link TracingObservationHandler} that handles {@link MongoHandlerContext}. It configures a span specific to Mongo
|
||||
* operations.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @author Greg Turnquist
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public class MongoTracingObservationHandler implements TracingObservationHandler<MongoHandlerContext> {
|
||||
|
||||
private static final Log log = LogFactory.getLog(MongoTracingObservationHandler.class);
|
||||
|
||||
private final Tracer tracer;
|
||||
|
||||
private boolean setRemoteIpAndPortEnabled;
|
||||
|
||||
public MongoTracingObservationHandler(Tracer tracer) {
|
||||
this.tracer = tracer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tracer getTracer() {
|
||||
return this.tracer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart(MongoHandlerContext context) {
|
||||
|
||||
CommandStartedEvent event = context.getCommandStartedEvent();
|
||||
|
||||
Span.Builder builder = this.tracer.spanBuilder() //
|
||||
.name(context.getContextualName()) //
|
||||
.kind(Span.Kind.CLIENT) //
|
||||
.remoteServiceName("mongodb-" + event.getDatabaseName());
|
||||
|
||||
if (this.setRemoteIpAndPortEnabled) {
|
||||
|
||||
ConnectionDescription connectionDescription = event.getConnectionDescription();
|
||||
|
||||
if (connectionDescription != null) {
|
||||
|
||||
try {
|
||||
|
||||
InetSocketAddress socketAddress = connectionDescription.getServerAddress().getSocketAddress();
|
||||
builder.remoteIpAndPort(socketAddress.getAddress().getHostAddress(), socketAddress.getPort());
|
||||
} catch (MongoSocketException e) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Ignored exception when setting remote ip and port", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getTracingContext(context).setSpan(builder.start());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop(MongoHandlerContext context) {
|
||||
|
||||
Span span = getRequiredSpan(context);
|
||||
tagSpan(context, span);
|
||||
|
||||
context.getRequestContext().delete(Observation.class);
|
||||
context.getRequestContext().delete(MongoHandlerContext.class);
|
||||
|
||||
span.end();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsContext(Observation.Context context) {
|
||||
return context instanceof MongoHandlerContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should remote ip and port be set on the span.
|
||||
*
|
||||
* @return {@code true} when the remote ip and port should be set
|
||||
*/
|
||||
public boolean isSetRemoteIpAndPortEnabled() {
|
||||
return this.setRemoteIpAndPortEnabled;
|
||||
}
|
||||
|
||||
public void setSetRemoteIpAndPortEnabled(boolean setRemoteIpAndPortEnabled) {
|
||||
this.setRemoteIpAndPortEnabled = setRemoteIpAndPortEnabled;
|
||||
}
|
||||
}
|
||||
@@ -61,7 +61,7 @@ class MongoCustomConversionsUnitTests {
|
||||
registry -> registry.registerConverter(Foo.class, "name", mock(PropertyValueConverter.class)));
|
||||
});
|
||||
|
||||
assertThat(conversions.hasPropertyValueConverter(persistentProperty)).isTrue();
|
||||
assertThat(conversions.getPropertyValueConversions().hasValueConverter(persistentProperty)).isTrue();
|
||||
}
|
||||
|
||||
static class DateToZonedDateTimeConverter implements Converter<Date, ZonedDateTime> {
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author 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.observability;
|
||||
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.core.instrument.observation.TimerObservationHandler;
|
||||
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
|
||||
import io.micrometer.observation.Observation;
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
import io.micrometer.tracing.Span;
|
||||
import io.micrometer.tracing.test.simple.SimpleTracer;
|
||||
import io.micrometer.tracing.test.simple.SpanAssert;
|
||||
import io.micrometer.tracing.test.simple.TracerAssert;
|
||||
|
||||
import org.bson.BsonDocument;
|
||||
import org.bson.BsonString;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.data.mongodb.observability.MongoObservation.HighCardinalityCommandKeyNames;
|
||||
import org.springframework.data.mongodb.observability.MongoObservation.LowCardinalityCommandKeyNames;
|
||||
|
||||
import com.mongodb.ServerAddress;
|
||||
import com.mongodb.connection.ClusterId;
|
||||
import com.mongodb.connection.ConnectionDescription;
|
||||
import com.mongodb.connection.ServerId;
|
||||
import com.mongodb.event.CommandFailedEvent;
|
||||
import com.mongodb.event.CommandStartedEvent;
|
||||
import com.mongodb.event.CommandSucceededEvent;
|
||||
|
||||
/**
|
||||
* Series of test cases exercising {@link MongoObservationCommandListener} to ensure proper creation of {@link Span}s.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @author Greg Turnquist
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class MongoObservationCommandListenerForTracingTests {
|
||||
|
||||
SimpleTracer simpleTracer;
|
||||
|
||||
MongoTracingObservationHandler handler;
|
||||
|
||||
MeterRegistry meterRegistry;
|
||||
ObservationRegistry observationRegistry;
|
||||
|
||||
MongoObservationCommandListener listener;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
|
||||
this.simpleTracer = new SimpleTracer();
|
||||
this.handler = new MongoTracingObservationHandler(simpleTracer);
|
||||
|
||||
this.meterRegistry = new SimpleMeterRegistry();
|
||||
this.observationRegistry = ObservationRegistry.create();
|
||||
this.observationRegistry.observationConfig().observationHandler(new TimerObservationHandler(meterRegistry));
|
||||
this.observationRegistry.observationConfig().observationHandler(handler);
|
||||
|
||||
this.listener = new MongoObservationCommandListener(observationRegistry);
|
||||
}
|
||||
|
||||
@Test
|
||||
void successfullyCompletedCommandShouldCreateSpanWhenParentSampleInRequestContext() {
|
||||
|
||||
// given
|
||||
TestRequestContext testRequestContext = createTestRequestContextWithParentObservationAndStartIt();
|
||||
|
||||
// when
|
||||
commandStartedAndSucceeded(testRequestContext);
|
||||
|
||||
// then
|
||||
assertThatMongoSpanIsClientWithTags().hasIpThatIsBlank().hasPortThatIsNotSet();
|
||||
}
|
||||
|
||||
@Test
|
||||
void successfullyCompletedCommandShouldCreateSpanWithAddressInfoWhenParentSampleInRequestContextAndHandlerAddressInfoEnabled() {
|
||||
|
||||
// given
|
||||
handler.setSetRemoteIpAndPortEnabled(true);
|
||||
TestRequestContext testRequestContext = createTestRequestContextWithParentObservationAndStartIt();
|
||||
|
||||
// when
|
||||
commandStartedAndSucceeded(testRequestContext);
|
||||
|
||||
// then
|
||||
assertThatMongoSpanIsClientWithTags().hasIpThatIsNotBlank().hasPortThatIsSet();
|
||||
}
|
||||
|
||||
@Test
|
||||
void commandWithErrorShouldCreateTimerWhenParentSampleInRequestContext() {
|
||||
|
||||
// given
|
||||
TestRequestContext testRequestContext = createTestRequestContextWithParentObservationAndStartIt();
|
||||
|
||||
// when
|
||||
listener.commandStarted(new CommandStartedEvent(testRequestContext, 0, //
|
||||
new ConnectionDescription( //
|
||||
new ServerId( //
|
||||
new ClusterId("description"), //
|
||||
new ServerAddress("localhost", 1234))), //
|
||||
"database", "insert", //
|
||||
new BsonDocument("collection", new BsonString("user"))));
|
||||
listener.commandFailed( //
|
||||
new CommandFailedEvent(testRequestContext, 0, null, "insert", 0, new IllegalAccessException()));
|
||||
|
||||
// then
|
||||
assertThatMongoSpanIsClientWithTags().assertThatThrowable().isInstanceOf(IllegalAccessException.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a parent {@link Observation} then wrap it inside a {@link TestRequestContext}.
|
||||
*/
|
||||
@NotNull
|
||||
private TestRequestContext createTestRequestContextWithParentObservationAndStartIt() {
|
||||
|
||||
Observation parent = Observation.start("name", observationRegistry);
|
||||
return TestRequestContext.withObservation(parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute MongoDB's {@link com.mongodb.event.CommandListener#commandStarted(CommandStartedEvent)} and
|
||||
* {@link com.mongodb.event.CommandListener#commandSucceeded(CommandSucceededEvent)} operations against the
|
||||
* {@link TestRequestContext} in order to inject some test data.
|
||||
*
|
||||
* @param testRequestContext
|
||||
*/
|
||||
private void commandStartedAndSucceeded(TestRequestContext testRequestContext) {
|
||||
|
||||
listener.commandStarted(new CommandStartedEvent(testRequestContext, 0, //
|
||||
new ConnectionDescription( //
|
||||
new ServerId( //
|
||||
new ClusterId("description"), //
|
||||
new ServerAddress("localhost", 1234))), //
|
||||
"database", "insert", //
|
||||
new BsonDocument("collection", new BsonString("user"))));
|
||||
|
||||
listener.commandSucceeded(new CommandSucceededEvent(testRequestContext, 0, null, "insert", null, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a base MongoDB-based {@link SpanAssert} using Micrometer Tracing's fluent API. Other test methods can apply
|
||||
* additional assertions.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private SpanAssert assertThatMongoSpanIsClientWithTags() {
|
||||
|
||||
return TracerAssert.assertThat(simpleTracer).onlySpan() //
|
||||
.hasNameEqualTo("insert user") //
|
||||
.hasKindEqualTo(Span.Kind.CLIENT) //
|
||||
.hasRemoteServiceNameEqualTo("mongodb-database") //
|
||||
.hasTag(HighCardinalityCommandKeyNames.MONGODB_COMMAND.getKeyName(), "insert") //
|
||||
.hasTag(LowCardinalityCommandKeyNames.MONGODB_COLLECTION.getKeyName(), "user") //
|
||||
.hasTagWithKey(LowCardinalityCommandKeyNames.MONGODB_CLUSTER_ID.getKeyName());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author 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.observability;
|
||||
|
||||
import static io.micrometer.core.tck.MeterRegistryAssert.*;
|
||||
|
||||
import io.micrometer.common.KeyValue;
|
||||
import io.micrometer.common.KeyValues;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.core.instrument.observation.TimerObservationHandler;
|
||||
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
|
||||
import io.micrometer.observation.Observation;
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
|
||||
import org.bson.BsonDocument;
|
||||
import org.bson.BsonString;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.data.mongodb.observability.MongoObservation.HighCardinalityCommandKeyNames;
|
||||
import org.springframework.data.mongodb.observability.MongoObservation.LowCardinalityCommandKeyNames;
|
||||
|
||||
import com.mongodb.ServerAddress;
|
||||
import com.mongodb.connection.ClusterId;
|
||||
import com.mongodb.connection.ConnectionDescription;
|
||||
import com.mongodb.connection.ServerId;
|
||||
import com.mongodb.event.CommandFailedEvent;
|
||||
import com.mongodb.event.CommandStartedEvent;
|
||||
import com.mongodb.event.CommandSucceededEvent;
|
||||
|
||||
/**
|
||||
* Series of test cases exercising {@link MongoObservationCommandListener}.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @author Greg Turnquist
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class MongoObservationCommandListenerTests {
|
||||
|
||||
ObservationRegistry observationRegistry;
|
||||
MeterRegistry meterRegistry;
|
||||
|
||||
MongoObservationCommandListener listener;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
|
||||
this.meterRegistry = new SimpleMeterRegistry();
|
||||
this.observationRegistry = ObservationRegistry.create();
|
||||
this.observationRegistry.observationConfig().observationHandler(new TimerObservationHandler(meterRegistry));
|
||||
|
||||
this.listener = new MongoObservationCommandListener(observationRegistry);
|
||||
}
|
||||
|
||||
@Test
|
||||
void commandStartedShouldNotInstrumentWhenAdminDatabase() {
|
||||
|
||||
// when
|
||||
listener.commandStarted(new CommandStartedEvent(null, 0, null, "admin", "", null));
|
||||
|
||||
// then
|
||||
assertThat(meterRegistry).hasNoMetrics();
|
||||
}
|
||||
|
||||
@Test
|
||||
void commandStartedShouldNotInstrumentWhenNoRequestContext() {
|
||||
|
||||
// when
|
||||
listener.commandStarted(new CommandStartedEvent(null, 0, null, "some name", "", null));
|
||||
|
||||
// then
|
||||
assertThat(meterRegistry).hasNoMetrics();
|
||||
}
|
||||
|
||||
@Test
|
||||
void commandStartedShouldNotInstrumentWhenNoParentSampleInRequestContext() {
|
||||
|
||||
// when
|
||||
listener.commandStarted(new CommandStartedEvent(new TestRequestContext(), 0, null, "some name", "", null));
|
||||
|
||||
// then
|
||||
assertThat(meterRegistry).hasNoMetrics();
|
||||
}
|
||||
|
||||
@Test
|
||||
void successfullyCompletedCommandShouldCreateTimerWhenParentSampleInRequestContext() {
|
||||
|
||||
// given
|
||||
Observation parent = Observation.start("name", observationRegistry);
|
||||
TestRequestContext testRequestContext = TestRequestContext.withObservation(parent);
|
||||
|
||||
// when
|
||||
listener.commandStarted(new CommandStartedEvent(testRequestContext, 0, //
|
||||
new ConnectionDescription( //
|
||||
new ServerId( //
|
||||
new ClusterId("description"), //
|
||||
new ServerAddress("localhost", 1234))),
|
||||
"database", "insert", //
|
||||
new BsonDocument("collection", new BsonString("user"))));
|
||||
listener.commandSucceeded(new CommandSucceededEvent(testRequestContext, 0, null, "insert", null, 0));
|
||||
|
||||
// then
|
||||
assertThatTimerRegisteredWithTags();
|
||||
}
|
||||
|
||||
@Test
|
||||
void successfullyCompletedCommandWithCollectionHavingCommandNameShouldCreateTimerWhenParentSampleInRequestContext() {
|
||||
|
||||
// given
|
||||
Observation parent = Observation.start("name", observationRegistry);
|
||||
TestRequestContext testRequestContext = TestRequestContext.withObservation(parent);
|
||||
|
||||
// when
|
||||
listener.commandStarted(new CommandStartedEvent(testRequestContext, 0, //
|
||||
new ConnectionDescription( //
|
||||
new ServerId( //
|
||||
new ClusterId("description"), //
|
||||
new ServerAddress("localhost", 1234))), //
|
||||
"database", "aggregate", //
|
||||
new BsonDocument("aggregate", new BsonString("user"))));
|
||||
listener.commandSucceeded(new CommandSucceededEvent(testRequestContext, 0, null, "aggregate", null, 0));
|
||||
|
||||
// then
|
||||
assertThatTimerRegisteredWithTags();
|
||||
}
|
||||
|
||||
@Test
|
||||
void successfullyCompletedCommandWithoutClusterInformationShouldCreateTimerWhenParentSampleInRequestContext() {
|
||||
|
||||
// given
|
||||
Observation parent = Observation.start("name", observationRegistry);
|
||||
TestRequestContext testRequestContext = TestRequestContext.withObservation(parent);
|
||||
|
||||
// when
|
||||
listener.commandStarted(new CommandStartedEvent(testRequestContext, 0, null, "database", "insert",
|
||||
new BsonDocument("collection", new BsonString("user"))));
|
||||
listener.commandSucceeded(new CommandSucceededEvent(testRequestContext, 0, null, "insert", null, 0));
|
||||
|
||||
// then
|
||||
assertThat(meterRegistry).hasTimerWithNameAndTags(HighCardinalityCommandKeyNames.MONGODB_COMMAND.getKeyName(),
|
||||
KeyValues.of(KeyValue.of(LowCardinalityCommandKeyNames.MONGODB_COLLECTION.getKeyName(), "user")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void commandWithErrorShouldCreateTimerWhenParentSampleInRequestContext() {
|
||||
|
||||
// given
|
||||
Observation parent = Observation.start("name", observationRegistry);
|
||||
TestRequestContext testRequestContext = TestRequestContext.withObservation(parent);
|
||||
|
||||
// when
|
||||
listener.commandStarted(new CommandStartedEvent(testRequestContext, 0, //
|
||||
new ConnectionDescription( //
|
||||
new ServerId( //
|
||||
new ClusterId("description"), //
|
||||
new ServerAddress("localhost", 1234))), //
|
||||
"database", "insert", //
|
||||
new BsonDocument("collection", new BsonString("user"))));
|
||||
listener.commandFailed( //
|
||||
new CommandFailedEvent(testRequestContext, 0, null, "insert", 0, new IllegalAccessException()));
|
||||
|
||||
// then
|
||||
assertThatTimerRegisteredWithTags();
|
||||
}
|
||||
|
||||
private void assertThatTimerRegisteredWithTags() {
|
||||
|
||||
assertThat(meterRegistry) //
|
||||
.hasTimerWithNameAndTags(HighCardinalityCommandKeyNames.MONGODB_COMMAND.getKeyName(),
|
||||
KeyValues.of(KeyValue.of(LowCardinalityCommandKeyNames.MONGODB_COLLECTION.getKeyName(), "user"))) //
|
||||
.hasTimerWithNameAndTagKeys(HighCardinalityCommandKeyNames.MONGODB_COMMAND.getKeyName(),
|
||||
LowCardinalityCommandKeyNames.MONGODB_CLUSTER_ID.getKeyName());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author 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.observability;
|
||||
|
||||
import io.micrometer.observation.Observation;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.mongodb.RequestContext;
|
||||
|
||||
/**
|
||||
* A {@link Map}-based {@link RequestContext}. (For test purposes only).
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @author Greg Turnquist
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class TestRequestContext implements RequestContext {
|
||||
|
||||
private final Map<Object, Object> map = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public <T> T get(Object key) {
|
||||
return (T) map.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasKey(Object key) {
|
||||
return map.containsKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return map.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(Object key, Object value) {
|
||||
map.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(Object key) {
|
||||
map.remove(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return map.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Map.Entry<Object, Object>> stream() {
|
||||
return map.entrySet().stream();
|
||||
}
|
||||
|
||||
static TestRequestContext withObservation(Observation value) {
|
||||
|
||||
TestRequestContext testRequestContext = new TestRequestContext();
|
||||
testRequestContext.put(Observation.class, value);
|
||||
return testRequestContext;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author 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.observability;
|
||||
|
||||
import static org.springframework.data.mongodb.test.util.Assertions.*;
|
||||
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.core.instrument.observation.TimerObservationHandler;
|
||||
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
|
||||
import io.micrometer.observation.Observation;
|
||||
import io.micrometer.observation.ObservationHandler;
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
import io.micrometer.tracing.test.SampleTestRunner;
|
||||
import io.micrometer.tracing.test.reporter.BuildingBlocks;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Deque;
|
||||
import java.util.List;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.PropertiesFactoryBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.data.mongodb.MongoDatabaseFactory;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory;
|
||||
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
|
||||
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverter;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.repository.Person;
|
||||
import org.springframework.data.mongodb.repository.PersonRepository;
|
||||
import org.springframework.data.mongodb.repository.SampleEvaluationContextExtension;
|
||||
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
|
||||
import org.springframework.data.mongodb.repository.support.MongoRepositoryFactoryBean;
|
||||
import org.springframework.data.repository.core.support.PropertiesBasedNamedQueries;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
import com.mongodb.ConnectionString;
|
||||
import com.mongodb.MongoClientSettings;
|
||||
import com.mongodb.RequestContext;
|
||||
import com.mongodb.WriteConcern;
|
||||
import com.mongodb.client.MongoClients;
|
||||
import com.mongodb.client.SynchronousContextProvider;
|
||||
|
||||
/**
|
||||
* Collection of tests that log metrics and tracing with an external tracing tool. Since this external tool must be up
|
||||
* and running after the test is completed, this test is ONLY run manually. Needed:
|
||||
* {@code docker run -p 9411:9411 openzipkin/zipkin} and {@code docker run -p 27017:27017 mongo:latest} (either from
|
||||
* Docker Desktop or within separate shells).
|
||||
*
|
||||
* @author Greg Turnquist
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@Disabled("Run this manually to visually test spans in Zipkin")
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@ContextConfiguration
|
||||
public class ZipkinIntegrationTests extends SampleTestRunner {
|
||||
|
||||
private static final MeterRegistry METER_REGISTRY = new SimpleMeterRegistry();
|
||||
private static final ObservationRegistry OBSERVATION_REGISTRY = ObservationRegistry.create();
|
||||
|
||||
static {
|
||||
OBSERVATION_REGISTRY.observationConfig().observationHandler(new TimerObservationHandler(METER_REGISTRY));
|
||||
}
|
||||
|
||||
@Autowired PersonRepository repository;
|
||||
|
||||
ZipkinIntegrationTests() {
|
||||
super(SampleRunnerConfig.builder().build(), OBSERVATION_REGISTRY, METER_REGISTRY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiConsumer<BuildingBlocks, Deque<ObservationHandler>> customizeObservationHandlers() {
|
||||
|
||||
return (buildingBlocks, observationHandlers) -> {
|
||||
observationHandlers.addLast(new MongoTracingObservationHandler(buildingBlocks.getTracer()));
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public TracingSetup[] getTracingSetup() {
|
||||
return new TracingSetup[] { TracingSetup.ZIPKIN_BRAVE };
|
||||
}
|
||||
|
||||
@Override
|
||||
public SampleTestRunnerConsumer yourCode() {
|
||||
|
||||
return (tracer, meterRegistry) -> {
|
||||
|
||||
repository.deleteAll();
|
||||
repository.save(new Person("Dave", "Matthews", 42));
|
||||
List<Person> people = repository.findByLastname("Matthews");
|
||||
|
||||
assertThat(people).hasSize(1);
|
||||
assertThat(people.get(0)).extracting("firstname", "lastname").containsExactly("Dave", "Matthews");
|
||||
|
||||
repository.deleteAll();
|
||||
|
||||
System.out.println(((SimpleMeterRegistry) meterRegistry).getMetersAsString());
|
||||
};
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableMongoRepositories
|
||||
static class TestConfig {
|
||||
|
||||
@Bean
|
||||
MongoObservationCommandListener mongoObservationCommandListener(ObservationRegistry registry) {
|
||||
return new MongoObservationCommandListener(registry);
|
||||
}
|
||||
|
||||
@Bean
|
||||
MongoDatabaseFactory mongoDatabaseFactory(MongoObservationCommandListener commandListener,
|
||||
ObservationRegistry registry) {
|
||||
|
||||
ConnectionString connectionString = new ConnectionString(
|
||||
String.format("mongodb://%s:%s/?w=majority&uuidrepresentation=javaLegacy", "127.0.0.1", 27017));
|
||||
|
||||
RequestContext requestContext = TestRequestContext.withObservation(Observation.start("name", registry));
|
||||
SynchronousContextProvider contextProvider = () -> requestContext;
|
||||
|
||||
MongoClientSettings settings = MongoClientSettings.builder() //
|
||||
.addCommandListener(commandListener) //
|
||||
.contextProvider(contextProvider) //
|
||||
.applyConnectionString(connectionString) //
|
||||
.build();
|
||||
|
||||
return new SimpleMongoClientDatabaseFactory(MongoClients.create(settings), "observable");
|
||||
}
|
||||
|
||||
@Bean
|
||||
MappingMongoConverter mongoConverter(MongoDatabaseFactory factory) {
|
||||
|
||||
MongoMappingContext mappingContext = new MongoMappingContext();
|
||||
mappingContext.afterPropertiesSet();
|
||||
|
||||
return new MappingMongoConverter(new DefaultDbRefResolver(factory), mappingContext);
|
||||
}
|
||||
|
||||
@Bean
|
||||
MongoTemplate mongoTemplate(MongoDatabaseFactory mongoDatabaseFactory, MongoConverter mongoConverter) {
|
||||
|
||||
MongoTemplate template = new MongoTemplate(mongoDatabaseFactory, mongoConverter);
|
||||
template.setWriteConcern(WriteConcern.JOURNALED);
|
||||
return template;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PropertiesFactoryBean namedQueriesProperties() {
|
||||
|
||||
PropertiesFactoryBean bean = new PropertiesFactoryBean();
|
||||
bean.setLocation(new ClassPathResource("META-INF/mongo-named-queries.properties"));
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Bean
|
||||
MongoRepositoryFactoryBean<PersonRepository, Person, String> repositoryFactoryBean(MongoOperations operations,
|
||||
PropertiesFactoryBean namedQueriesProperties) throws IOException {
|
||||
|
||||
MongoRepositoryFactoryBean<PersonRepository, Person, String> factoryBean = new MongoRepositoryFactoryBean<>(
|
||||
PersonRepository.class);
|
||||
factoryBean.setMongoOperations(operations);
|
||||
factoryBean.setNamedQueries(new PropertiesBasedNamedQueries(namedQueriesProperties.getObject()));
|
||||
factoryBean.setCreateIndexesForQueryMethods(true);
|
||||
return factoryBean;
|
||||
}
|
||||
|
||||
@Bean
|
||||
SampleEvaluationContextExtension contextExtension() {
|
||||
return new SampleEvaluationContextExtension();
|
||||
}
|
||||
|
||||
@Bean
|
||||
ObservationRegistry registry() {
|
||||
return OBSERVATION_REGISTRY;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,3 +42,4 @@ include::{spring-data-commons-docs}/repository-namespace-reference.adoc[leveloff
|
||||
include::{spring-data-commons-docs}/repository-populator-namespace-reference.adoc[leveloffset=+1]
|
||||
include::{spring-data-commons-docs}/repository-query-keywords-reference.adoc[leveloffset=+1]
|
||||
include::{spring-data-commons-docs}/repository-query-return-types-reference.adoc[leveloffset=+1]
|
||||
include::reference/observability.adoc[leveloffset=+1]
|
||||
|
||||
@@ -115,4 +115,4 @@ Professional Support :: Professional, from-the-source support, with guaranteed r
|
||||
[[get-started:up-to-date]]
|
||||
== Following Development
|
||||
|
||||
For information on the Spring Data Mongo source code repository, nightly builds, and snapshot artifacts, see the Spring Data Mongo https://projects.spring.io/spring-data-mongodb/[homepage]. You can help make Spring Data best serve the needs of the Spring community by interacting with developers through the Community on https://stackoverflow.com/questions/tagged/spring-data[Stack Overflow]. To follow developer activity, look for the mailing list information on the Spring Data Mongo https://projects.spring.io/spring-data-mongodb/[homepage]. If you encounter a bug or want to suggest an improvement, please create a ticket on the Spring Data https://github.com/spring-projects/spring-data-mongodb/issues[issue tracker]. To stay up to date with the latest news and announcements in the Spring eco system, subscribe to the Spring Community https://spring.io[Portal]. You can also follow the Spring https://spring.io/blog[blog] or the project team on Twitter (https://twitter.com/SpringData[SpringData]).
|
||||
For information on the Spring Data Mongo source code repository, nightly builds, and snapshot artifacts, see the Spring Data Mongo https://spring.io/projects/spring-data-mongodb/[homepage]. You can help make Spring Data best serve the needs of the Spring community by interacting with developers through the Community on https://stackoverflow.com/questions/tagged/spring-data[Stack Overflow]. To follow developer activity, look for the mailing list information on the Spring Data Mongo https://spring.io/projects/spring-data-mongodb/[homepage]. If you encounter a bug or want to suggest an improvement, please create a ticket on the Spring Data https://github.com/spring-projects/spring-data-mongodb/issues[issue tracker]. To stay up to date with the latest news and announcements in the Spring eco system, subscribe to the Spring Community https://spring.io[Portal]. You can also follow the Spring https://spring.io/blog[blog] or the project team on Twitter (https://twitter.com/SpringData[SpringData]).
|
||||
|
||||
@@ -162,7 +162,7 @@ calling `get()` before the actual conversion
|
||||
|
||||
| `URL`
|
||||
| converter
|
||||
| `{"website" : "https://projects.spring.io/spring-data-mongodb/" }`
|
||||
| `{"website" : "https://spring.io/projects/spring-data-mongodb/" }`
|
||||
|
||||
| `Locale`
|
||||
| converter
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
[[mongo.property-converters]]
|
||||
== Property Converters - Mapping specific fields
|
||||
|
||||
While <<mongo.custom-converters, type-based conversion>> already offers ways to influence the conversion and representation of certain types within the target store it has its limitations when only certain values or properties of a particular type should be considered for conversion.
|
||||
Property-based converters allow configuring conversion rules on a per-property basis, either declarative, via `@ValueConverter`, or programmatic by registering a `PropertyValueConverter` for a specific property.
|
||||
While <<mongo.custom-converters, type-based conversion>> already offers ways to influence the conversion and representation of certain types within the target store, it has limitations when only certain values or properties of a particular type should be considered for conversion.
|
||||
Property-based converters allow configuring conversion rules on a per-property basis, either declaratively (via `@ValueConverter`) or programmatically (by registering a `PropertyValueConverter` for a specific property).
|
||||
|
||||
A `PropertyValueConverter` can transform a given value into its store representation (**write**) and back (**read**) as shown in the snippet below.
|
||||
The additional `ValueConversionContext` provides additional information, such as mapping metadata and direct `read`/`write` methods.
|
||||
A `PropertyValueConverter` can transform a given value into its store representation (write) and back (read) as the following listing shows.
|
||||
The additional `ValueConversionContext` provides additional information, such as mapping metadata and direct `read` and `write` methods.
|
||||
|
||||
.A simple PropertyValueConverter
|
||||
====
|
||||
@@ -26,18 +26,18 @@ class ReversingValueConverter implements PropertyValueConverter<String, String,
|
||||
----
|
||||
====
|
||||
|
||||
`PropertyValueConverter` instances can be obtained via `CustomConversions#getPropertyValueConverter(…)` delegating to `PropertyValueConversions`, typically using a `PropertyValueConverterFactory` providing the actual converter.
|
||||
Depending on the applications needs, multiple instances of `PropertyValueConverterFactory` can be chained or decorated, for example to apply caching.
|
||||
By default, a caching implementation is used that is capable of serving types with a default constructor or enum values.
|
||||
A set of predefined factories is available through `PropertyValueConverterFactory` factory methods.
|
||||
Use `PropertyValueConverterFactory.beanFactoryAware(…)` to obtain a `PropertyValueConverter` instances from an `ApplicationContext`.
|
||||
You can obtain `PropertyValueConverter` instances from `CustomConversions#getPropertyValueConverter(…)` by delegating to `PropertyValueConversions`, typically by using a `PropertyValueConverterFactory` to provide the actual converter.
|
||||
Depending on your application's needs, you can chain or decorate multiple instances of `PropertyValueConverterFactory` -- for example, to apply caching.
|
||||
By default, Spring Data MongoDB uses a caching implementation that can serve types with a default constructor or enum values.
|
||||
A set of predefined factories is available through the factory methods in `PropertyValueConverterFactory`.
|
||||
You can use `PropertyValueConverterFactory.beanFactoryAware(…)` to obtain a `PropertyValueConverter` instance from an `ApplicationContext`.
|
||||
|
||||
You can change the default behavior through `ConverterConfiguration`.
|
||||
|
||||
[[mongo.property-converters.declarative]]
|
||||
=== Declarative Value Converter
|
||||
|
||||
The most straight forward usage of a `PropertyValueConverter` is by annotating properties with the `@ValueConverter` annotation that defines the converter type.
|
||||
The most straight forward usage of a `PropertyValueConverter` is by annotating properties with the `@ValueConverter` annotation that defines the converter type:
|
||||
|
||||
.Declarative PropertyValueConverter
|
||||
====
|
||||
@@ -54,8 +54,8 @@ class Person {
|
||||
[[mongo.property-converters.programmatic]]
|
||||
=== Programmatic Value Converter Registration
|
||||
|
||||
Programmatic registration registers `PropertyValueConverter` instances for properties within an entity model using a `PropertyValueConverterRegistrar` as shown below.
|
||||
The difference to declarative registration is that programmatic registration happens entirely outside of the entity model.
|
||||
Programmatic registration registers `PropertyValueConverter` instances for properties within an entity model by using a `PropertyValueConverterRegistrar`, as the following example shows.
|
||||
The difference between declarative registration and programmatic registration is that programmatic registration happens entirely outside of the entity model.
|
||||
Such an approach is useful if you cannot or do not want to annotate the entity model.
|
||||
|
||||
.Programmatic PropertyValueConverter registration
|
||||
@@ -76,25 +76,22 @@ registrar.registerConverter(Person.class, Person::getSsn())
|
||||
<2> Type safe variant that allows to register a converter and its conversion functions.
|
||||
====
|
||||
|
||||
[WARNING]
|
||||
====
|
||||
Dot-notation (such as `registerConverter(Person.class, "address.street", …)`) nagivating across properties into subdocuments is *not* supported when registering converters.
|
||||
====
|
||||
WARNING: Dot notation (such as `registerConverter(Person.class, "address.street", …)`) for nagivating across properties into subdocuments is *not* supported when registering converters.
|
||||
|
||||
[[mongo.property-converters.value-conversions]]
|
||||
=== MongoDB property value conversions
|
||||
|
||||
The above sections outlined the purpose an overall structure of `PropertyValueConverters`.
|
||||
This section will focus on MongoDB specific aspects.
|
||||
The preceding sections outlined the purpose an overall structure of `PropertyValueConverters`.
|
||||
This section focuses on MongoDB specific aspects.
|
||||
|
||||
==== MongoValueConverter and MongoConversionContext
|
||||
|
||||
`MongoValueConverter` offers a pre typed `PropertyValueConverter` interface leveraging the `MongoConversionContext`.
|
||||
`MongoValueConverter` offers a pre-typed `PropertyValueConverter` interface that uses `MongoConversionContext`.
|
||||
|
||||
==== MongoCustomConversions configuration
|
||||
|
||||
`MongoCustomConversions` are by default capable of handling declarative value converters depending on the configured `PropertyValueConverterFactory`.
|
||||
`MongoConverterConfigurationAdapter` is there to help set up programmatic value conversions or define the `PropertyValueConverterFactory` to be used.
|
||||
By default, `MongoCustomConversions` can handle declarative value converters, depending on the configured `PropertyValueConverterFactory`.
|
||||
`MongoConverterConfigurationAdapter` helps to set up programmatic value conversions or define the `PropertyValueConverterFactory` to be used.
|
||||
|
||||
.Configuration Sample
|
||||
====
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
= MongoDB Repositories
|
||||
|
||||
[[mongo-repo-intro]]
|
||||
== Introduction
|
||||
|
||||
This chapter points out the specialties for repository support for MongoDB. This chapter builds on the core repository support explained in <<repositories>>. You should have a sound understanding of the basic concepts explained there.
|
||||
|
||||
[[mongo-repo-usage]]
|
||||
@@ -292,13 +290,13 @@ NOTE: If the property criterion compares a document, the order of the fields and
|
||||
[[mongodb.repositories.queries.update]]
|
||||
=== Repository Update Methods
|
||||
|
||||
The keywords in the preceding table can also be used to create queries that identify matching documents for running updates on them.
|
||||
The actual update action is defined via the `@Update` annotation on the method itself as shown in the snippet below. +
|
||||
Please note that the naming schema for derived queries starts with `find`.
|
||||
Using _update_ (as in `updateAllByLastname(...)`) is only allowed in combination with `@Query`.
|
||||
You can also use the keywords in the preceding table to create queries that identify matching documents for running updates on them.
|
||||
The actual update action is defined by the `@Update` annotation on the method itself, as the following listing shows.
|
||||
Note that the naming schema for derived queries starts with `find`.
|
||||
Using `update` (as in `updateAllByLastname(...)`) is allowed only in combination with `@Query`.
|
||||
|
||||
The update is applied to *all* matching documents and it is *not* possible to limit the scope by passing in a `Page` nor using any of the <<repositories.limit-query-result,limiting keywords>>. +
|
||||
The return type can be either `void` or a _numeric_ type, such as `long` which holds the number of modified documents.
|
||||
The update is applied to *all* matching documents and it is *not* possible to limit the scope by passing in a `Page` or by using any of the <<repositories.limit-query-result,limiting keywords>>.
|
||||
The return type can be either `void` or a _numeric_ type, such as `long`, to hold the number of modified documents.
|
||||
|
||||
.Update Methods
|
||||
====
|
||||
@@ -326,18 +324,15 @@ public interface PersonRepository extends CrudRepository<Person, String> {
|
||||
void updateAllByLastname(String lastname, int increment); <6>
|
||||
}
|
||||
----
|
||||
<1> The filter query for the update is derived from the method name. The update is as is and does not bind any parameters.
|
||||
<2> The actual increment value is defined by the _increment_ method argument that is bound to the `?1` placeholder.
|
||||
<3> It is possible to use SpEL for parameter binding.
|
||||
<1> The filter query for the update is derived from the method name. The update is "`as is`" and does not bind any parameters.
|
||||
<2> The actual increment value is defined by the `increment` method argument that is bound to the `?1` placeholder.
|
||||
<3> Use the Spring Expression Language (SpEL) for parameter binding.
|
||||
<4> Use the `pipeline` attribute to issue <<mongo-template.aggregation-update,aggregation pipeline updates>>.
|
||||
<5> The update may contain complex objects.
|
||||
<6> Combine a <<mongodb.repositories.queries.json-based,string based query>> with an update.
|
||||
====
|
||||
|
||||
[WARNING]
|
||||
====
|
||||
Repository updates do not emit persistence nor mapping lifecycle events.
|
||||
====
|
||||
WARNING: Repository updates do not emit persistence nor mapping lifecycle events.
|
||||
|
||||
[[mongodb.repositories.queries.delete]]
|
||||
=== Repository Delete Queries
|
||||
|
||||
8
src/main/asciidoc/reference/observability.adoc
Normal file
8
src/main/asciidoc/reference/observability.adoc
Normal file
@@ -0,0 +1,8 @@
|
||||
:root-target: ../../../../target/
|
||||
|
||||
[[observability]]
|
||||
== Observability metadata
|
||||
|
||||
include::{root-target}_metrics.adoc[]
|
||||
|
||||
include::{root-target}_spans.adoc[]
|
||||
@@ -1,4 +1,4 @@
|
||||
Spring Data MongoDB 4.0 M2 (2022.0.0)
|
||||
Spring Data MongoDB 4.0 M4 (2022.0.0)
|
||||
Copyright (c) [2010-2019] Pivotal Software, Inc.
|
||||
|
||||
This product is licensed to you under the Apache License, Version 2.0 (the "License").
|
||||
@@ -32,6 +32,8 @@ conditions of the subcomponent's license, as noted in the LICENSE file.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user