Коммит
3de8cea808
|
@ -1,5 +1,6 @@
|
|||
# Compiled class file
|
||||
*.class
|
||||
.classpath
|
||||
|
||||
# Log file
|
||||
*.log
|
||||
|
@ -20,3 +21,23 @@
|
|||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
|
||||
# IntelliJ
|
||||
.idea
|
||||
*.iml
|
||||
.project
|
||||
.settings
|
||||
|
||||
# Eclipse
|
||||
.metadata
|
||||
.checkstyle
|
||||
.fbExcludeFilterFile
|
||||
|
||||
#Spring
|
||||
.springBeans
|
||||
.factorypath
|
||||
|
||||
# Maven
|
||||
target
|
||||
/bin/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
|
@ -0,0 +1,5 @@
|
|||
language: java
|
||||
jdk:
|
||||
- oraclejdk8
|
||||
|
||||
script: "./mvnw clean install"
|
163
README.md
163
README.md
|
@ -1,14 +1,157 @@
|
|||
## Spring Data for Azure Cosmos DB DocumentDB API
|
||||
[Azure Cosmos DB](https://docs.microsoft.com/en-us/azure/cosmos-db/introduction) is a globally-distributed database service that allows developers to work with data using a variety of standard APIs, such as DocumentDB, MongoDB, Graph, and Table APIs. Azure DocumentDB Spring Data provides initial Spring Data support for [Azure Cosmos DB Document API](https://docs.microsoft.com/en-us/azure/cosmos-db/documentdb-introduction) based on Spring Data framework, the other 3 APIs are not supported in this package. Key functionalities supported so far include save, delete and find. More features will coming soon.
|
||||
|
||||
# Contributing
|
||||
## Sample Code
|
||||
Please refer to [sample project here](./samplecode).
|
||||
|
||||
This project welcomes contributions and suggestions. Most contributions require you to agree to a
|
||||
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
|
||||
the rights to use your contribution. For details, visit https://cla.microsoft.com.
|
||||
## Feature List
|
||||
- Spring Data CRUDRepository basic CRUD functionality
|
||||
- save
|
||||
- findAll
|
||||
- findOne by Id
|
||||
- deleteAll
|
||||
- delete by Id
|
||||
- delete entity
|
||||
- Spring Data [@Id](https://github.com/spring-projects/spring-data-commons/blob/db62390de90c93a78743c97cc2cc9ccd964994a5/src/main/java/org/springframework/data/annotation/Id.java) annotation.
|
||||
There're 2 ways to map a field in domain class to `id` of Azure Cosmos DB document.
|
||||
- annotate a field in domain class with `@Id`, this field will be mapped to document `id` in Cosmos DB.
|
||||
- set name of this field to `id`, this field will be mapped to document `id` in Cosmos DB.
|
||||
- Custom collection Name.
|
||||
By default, collection name will be class name of user domain class. To customize it, add annoataion `@Document(collection="myCustomCollectionName")` to your domain class, that's all.
|
||||
- Supports [Azure Cosmos DB partition](https://docs.microsoft.com/en-us/azure/cosmos-db/partition-data). To specify a field of your domain class to be partition key field, just annotate it with `@PartitionKey`. When you do CRUD operation, pls specify your partition value. For more sample on partition CRUD, pls refer to [test here](./test/java/com/microsoft/azure/spring/data/documentdb/repository/AddressRepositoryIT.java)
|
||||
|
||||
## Quick Start
|
||||
|
||||
When you submit a pull request, a CLA-bot will automatically determine whether you need to provide
|
||||
a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions
|
||||
provided by the bot. You will only need to do this once across all repos using our CLA.
|
||||
### Add the dependency
|
||||
`spring-data-azure-cosmosdb-documentdb` is published on Maven Central Repository.
|
||||
If you are using Maven, add the following dependency.
|
||||
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
|
||||
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
|
||||
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>com.microsoft.azure</groupId>
|
||||
<artifactId>spring-data-azure-cosmosdb-documentdb</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
### Setup Configuration
|
||||
Setup Azure Cosmos DB DocumentDB configuration class. Enabling Spring Data Azure DocumentDB repository support is auto-configured.
|
||||
|
||||
```
|
||||
@Configuration
|
||||
public class AppConfiguration extends AbstractDocumentDbConfiguration {
|
||||
|
||||
@Value("${azure.documentdb.uri}")
|
||||
private String uri;
|
||||
|
||||
@Value("${azure.documentdb.key}")
|
||||
private String key;
|
||||
|
||||
@Value("${azure.documentdb.database}")
|
||||
private String dbName;
|
||||
|
||||
public DocumentClient documentClient() {
|
||||
return new DocumentClient(uri, key, ConnectionPolicy.GetDefault(), ConsistencyLevel.Session);
|
||||
}
|
||||
|
||||
public String getDatabase() {
|
||||
return dbName;
|
||||
}
|
||||
}
|
||||
```
|
||||
By default, `@EnableDocumentDbRepositories` will scan the current package for any interfaces that extend one of Spring Data's repository interfaces. Using it to annotate your Configuration class to scan a different root package by type if your project layout has multiple projects and it's not finding your repositories.
|
||||
```
|
||||
@Configuration
|
||||
@EnableDocumentDbRepositories(basePackageClass=UserRepository.class)
|
||||
public class AppConfiguration extends AbstractDocumentDbConfiguration {
|
||||
// configuration code
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Define en entity
|
||||
Define a simple entity as Document in DocumentDB.
|
||||
|
||||
```
|
||||
@Document(collection = "mycollection")
|
||||
public class User {
|
||||
private String id;
|
||||
private String firstName;
|
||||
@PartitionKey
|
||||
private String lastName;
|
||||
|
||||
... // setters and getters
|
||||
|
||||
public User(String id, String firstName, String lastName) {
|
||||
this.id = id;
|
||||
this.firstName = firstName;
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("User: %s %s, %s", firstName, lastName);
|
||||
}
|
||||
}
|
||||
```
|
||||
`id` field will be used as document id in Azure DocumentDB. If you want use another field like `emailAddress` as document `id`, just annotate that field with `@Id` annotation.
|
||||
|
||||
Annotation `@Document(collection="mycollection")` is used to specify collection name of your document in Azure Cosmos DB.
|
||||
Annotation `@PartitionKey` on lastName field is used to specify this field be partition key in Azure Cosmos DB.
|
||||
|
||||
```
|
||||
@Document(collection = "mycollection")
|
||||
public class User {
|
||||
@Id
|
||||
private String emailAddress;
|
||||
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
### Create repositories
|
||||
Extends DocumentDbRepository interface, which provides Spring Data repository support.
|
||||
|
||||
```
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.repository.DocumentDbRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface UserRepository extends DocumentDbRepository<User, String> {
|
||||
}
|
||||
```
|
||||
|
||||
So far DocumentDbRepository provides basic save, delete and find operations. More operations will be supported later.
|
||||
|
||||
### Create an Application class
|
||||
Here create an application class with all the components
|
||||
|
||||
```
|
||||
@SpringBootApplication
|
||||
public class SampleApplication implements CommandLineRunner {
|
||||
|
||||
@Autowired
|
||||
private UserRepository repository;
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SampleApplication.class, args);
|
||||
}
|
||||
|
||||
public void run(String... var1) throws Exception {
|
||||
|
||||
final User testUser = new User("testId", "testFirstName", "testLastName");
|
||||
|
||||
repository.deleteAll();
|
||||
repository.save(testUser);
|
||||
|
||||
// to find by Id, please specify partition key value if collection is partitioned
|
||||
final User result = repository.findOne(testUser.getId(), testUser.getLastName);
|
||||
// if emailAddress is mapped to id, then
|
||||
// final User result = respository.findOne(testUser.getEmailAddress(), testUser.getLastName());
|
||||
}
|
||||
}
|
||||
```
|
||||
Autowired UserRepository interface, then can do save, delete and find operations. Azure Cosmos DB DocumentDB Spring Data uses the DocumentTemplate to execute the queries behind *find*, *save* methods. You can use the template yourself for more complex queries.
|
||||
|
||||
## Further info
|
||||
If you'd like to save effort of configuration, you could directly use Azure Cosmos DB DocumentDB API Spring boot starter at [here](../azure-documentdb-spring-boot-starter).
|
|
@ -0,0 +1,39 @@
|
|||
image: Visual Studio 2017
|
||||
|
||||
environment:
|
||||
JAVA_HOME: "C:\\Program Files\\Java\\jdk1.8.0"
|
||||
PYTHON: "C:\\Python35"
|
||||
CODECOV_UPLOAD_TOKEN:
|
||||
secure: 80IcEvO4OmyIeu2O4Yq7fKr4BV9p3M6zczwEAy2bL/H1CzypXF4PEpDGyACNTdX1
|
||||
|
||||
install:
|
||||
- cmd: python -m pip install codecov
|
||||
- cmd: copy "C:\Program Files (x86)\Apache\Maven\bin\mvn.cmd" "C:\Program Files (x86)\Apache\Maven\bin\mvn.bat"
|
||||
- cmd: net share "c=c:"
|
||||
# 1. starter docker
|
||||
- ps: Start-Process "C:\Program Files\Docker\dockerd.exe"
|
||||
# 2. starter emulator
|
||||
- cmd: docker pull microsoft/azure-cosmosdb-emulator
|
||||
- cmd: md %LOCALAPPDATA%\CosmosDBEmulatorCert 2>nul
|
||||
- cmd: docker run -d -v %LOCALAPPDATA%\CosmosDBEmulatorCert:c:\CosmosDBEmulator\CosmosDBEmulatorCert -p 8081:8081 -t -i microsoft/azure-cosmosdb-emulator >> dockerid.txt
|
||||
- cmd: set /P dockerid=<dockerid.txt
|
||||
- cmd: timeout 100
|
||||
- cmd: docker logs %dockerid% >> dockerlog.txt
|
||||
- ps: $substtring = type dockerlog.txt | where { $_ -match "\bhttps://[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+:8081/$" } | foreach { $matches[0] }; $substtring | Out-File -filepath documentdburi.txt -encoding ASCII
|
||||
- cmd: set /P DOCUMENTDB_URI=< documentdburi.txt
|
||||
# 3. import cert
|
||||
- ps: cd C:\Users\appveyor\AppData\Local\CosmosDBEmulatorCert; .\importcert.ps1
|
||||
# 4. export cert to java cert store
|
||||
- ps: $cert = Get-ChildItem cert:\LocalMachine\my | Where-Object { $_.FriendlyName -eq "DocumentDbEmulatorCertificate"}; export-Certificate -filepath c:\documentdb.cer -cert ${cert} -type CERT -NoClobber
|
||||
- cmd: cd "C:\Program Files\Java\jdk1.8.0\jre\lib\security"
|
||||
- cmd: certutil -encode c:\documentdb.cer documentdbemulatordb.cer
|
||||
- cmd: keytool -keystore cacerts -importcert -alias documentdbemulatorcert -file .\documentdbemulatordb.cer -storepass changeit -trustcacerts -noprompt
|
||||
- cmd: cd "C:\projects\azure-spring-boot-starters"
|
||||
|
||||
|
||||
build_script:
|
||||
- mvn clean install -B -V
|
||||
|
||||
after_build:
|
||||
- mvn -P integration-test-emulator cobertura:cobertura-integration-test
|
||||
- ps: Get-ChildItem -Path . -Recurse -File -Filter coverage.xml | Foreach-Object { codecov -f $_.FullName -t $Env:CODECOV_UPLOAD_TOKEN -X gcov }
|
|
@ -0,0 +1,37 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<project name="test resource prepration and cleanup">
|
||||
<target name="setup">
|
||||
<echo message="setup test resource"/>
|
||||
<exec osfamily="windows" executable="cmd.exe">
|
||||
<arg value="/c"/>
|
||||
<arg value=".\src\libs\setup.bat"/>
|
||||
<arg value="${azure.test.resourcegroup}"/>
|
||||
<arg value="${azure.test.dbname}"/>
|
||||
<redirector outputproperty="documentdb.key"/>
|
||||
</exec>
|
||||
<exec osfamily="unix" executable="bash">
|
||||
<arg value="./src/libs/setup.sh"/>
|
||||
<arg value="${azure.test.resourcegroup}"/>
|
||||
<arg value="${azure.test.dbname}"/>
|
||||
<redirector outputproperty="documentdb.key"/>
|
||||
</exec>
|
||||
<propertyfile file="./src/test/resources/application.properties">
|
||||
<entry key="documentdb.key" value="${documentdb.key}"/>
|
||||
<entry key="documentdb.uri" value="https://${azure.test.dbname}.documents.azure.com:443"/>
|
||||
</propertyfile>
|
||||
</target>
|
||||
<target name="cleanup">
|
||||
<echo message="cleanup test resource"/>
|
||||
<exec osfamily="windows" executable="cmd.exe">
|
||||
<arg value="/c"/>
|
||||
<arg value=".\src\libs\cleanup.bat"/>
|
||||
<arg value="${azure.test.resourcegroup}"/>
|
||||
<arg value="${azure.test.dbname}"/>
|
||||
</exec>
|
||||
<exec osfamily="unix" executable="bash">
|
||||
<arg value="./src/libs/cleanup.sh"/>
|
||||
<arg value="${azure.test.resourcegroup}"/>
|
||||
<arg value="${azure.test.dbname}"/>
|
||||
</exec>
|
||||
</target>
|
||||
</project>
|
|
@ -0,0 +1,296 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!DOCTYPE module PUBLIC
|
||||
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
|
||||
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
|
||||
|
||||
<!-- This is a checkstyle configuration file. For descriptions of
|
||||
what the following rules do, please see the checkstyle configuration
|
||||
page at http://checkstyle.sourceforge.net/config.html -->
|
||||
|
||||
<module name="Checker">
|
||||
|
||||
<module name="SuppressionFilter">
|
||||
</module>
|
||||
|
||||
<module name="Header">
|
||||
<property name="header"
|
||||
value="/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See LICENSE in the project root for\n * license information.\n */"/>
|
||||
<property name="fileExtensions" value="java"/>
|
||||
</module>
|
||||
|
||||
<module name="FileTabCharacter">
|
||||
<!-- Checks that there are no tab characters in the file.
|
||||
-->
|
||||
</module>
|
||||
|
||||
<module name="NewlineAtEndOfFile">
|
||||
<property name="lineSeparator" value="lf"/>
|
||||
</module>
|
||||
|
||||
<module name="RegexpSingleline">
|
||||
<!-- Checks that FIXME is not used in comments. TODO is preferred.
|
||||
-->
|
||||
<property name="format" value="((//.*)|(\*.*))FIXME"/>
|
||||
<property name="message"
|
||||
value='TODO is preferred to FIXME. e.g. "TODO(johndoe): Refactor when v2 is released."'/>
|
||||
</module>
|
||||
|
||||
<module name="RegexpSingleline">
|
||||
<!-- Checks that TODOs are named. (Actually, just that they are followed
|
||||
by an open paren.)
|
||||
-->
|
||||
<property name="format" value="((//.*)|(\*.*))TODO [^(]"/>
|
||||
<property name="message"
|
||||
value='All TODOs should be named. e.g. "TODO (johndoe): Refactor when v2 is released."'/>
|
||||
</module>
|
||||
|
||||
<!-- All Java AST specific tests live under TreeWalker module. -->
|
||||
<module name="TreeWalker">
|
||||
|
||||
<!--
|
||||
|
||||
IMPORT CHECKS
|
||||
|
||||
-->
|
||||
|
||||
<module name="RedundantImport">
|
||||
<!-- Checks for redundant import statements. -->
|
||||
<property name="severity" value="error"/>
|
||||
</module>
|
||||
|
||||
<!--
|
||||
|
||||
NAMING CHECKS
|
||||
|
||||
-->
|
||||
|
||||
<!-- Item 38 - Adhere to generally accepted naming conventions -->
|
||||
|
||||
<module name="PackageName">
|
||||
<!-- Validates identifiers for package names against the
|
||||
supplied expression. -->
|
||||
<!-- Here the default checkstyle rule restricts package name parts to
|
||||
seven characters, this is not in line with common practice at Google.
|
||||
-->
|
||||
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]{1,})*$"/>
|
||||
<property name="severity" value="warning"/>
|
||||
</module>
|
||||
|
||||
<module name="TypeNameCheck">
|
||||
<!-- Validates static, final fields against the
|
||||
expression "^[A-Z][a-zA-Z0-9]*$". -->
|
||||
<metadata name="altname" value="TypeName"/>
|
||||
<property name="severity" value="warning"/>
|
||||
</module>
|
||||
|
||||
<module name="ConstantNameCheck">
|
||||
<!-- Validates non-private, static, final fields against the supplied
|
||||
public/package final fields "^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$". -->
|
||||
<metadata name="altname" value="ConstantName"/>
|
||||
<property name="applyToPublic" value="true"/>
|
||||
<property name="applyToProtected" value="true"/>
|
||||
<property name="applyToPackage" value="true"/>
|
||||
<property name="applyToPrivate" value="false"/>
|
||||
<property name="format" value="^([A-Z][A-Z0-9]*(_[A-Z0-9]+)*|FLAG_.*)$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Variable ''{0}'' should be in ALL_CAPS (if it is a constant) or be private (otherwise)."/>
|
||||
<property name="severity" value="warning"/>
|
||||
</module>
|
||||
|
||||
<module name="StaticVariableNameCheck">
|
||||
<!-- Validates static, non-final fields against the supplied
|
||||
expression "^[a-z][a-zA-Z0-9]*_?$". -->
|
||||
<metadata name="altname" value="StaticVariableName"/>
|
||||
<property name="applyToPublic" value="true"/>
|
||||
<property name="applyToProtected" value="true"/>
|
||||
<property name="applyToPackage" value="true"/>
|
||||
<property name="applyToPrivate" value="true"/>
|
||||
<property name="format" value="^[a-z][a-zA-Z0-9]*_?$"/>
|
||||
<property name="severity" value="warning"/>
|
||||
</module>
|
||||
|
||||
<module name="MemberNameCheck">
|
||||
<!-- Validates non-static members against the supplied expression. -->
|
||||
<metadata name="altname" value="MemberName"/>
|
||||
<property name="applyToPublic" value="true"/>
|
||||
<property name="applyToProtected" value="true"/>
|
||||
<property name="applyToPackage" value="true"/>
|
||||
<property name="applyToPrivate" value="true"/>
|
||||
<property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
|
||||
<property name="severity" value="warning"/>
|
||||
</module>
|
||||
|
||||
<module name="MethodNameCheck">
|
||||
<!-- Validates identifiers for method names. -->
|
||||
<metadata name="altname" value="MethodName"/>
|
||||
<property name="format" value="^[a-z][a-zA-Z0-9]*(_[a-zA-Z0-9]+)*$"/>
|
||||
<property name="severity" value="warning"/>
|
||||
</module>
|
||||
|
||||
<module name="ParameterName">
|
||||
<!-- Validates identifiers for method parameters against the
|
||||
expression "^[a-z][a-zA-Z0-9]*$". -->
|
||||
<property name="severity" value="warning"/>
|
||||
</module>
|
||||
|
||||
<module name="LocalFinalVariableName">
|
||||
<!-- Validates identifiers for local final variables against the
|
||||
expression "^[a-z][a-zA-Z0-9]*$". -->
|
||||
<property name="severity" value="warning"/>
|
||||
</module>
|
||||
|
||||
<module name="LocalVariableName">
|
||||
<!-- Validates identifiers for local variables against the
|
||||
expression "^[a-z][a-zA-Z0-9]*$". -->
|
||||
<property name="severity" value="warning"/>
|
||||
</module>
|
||||
|
||||
<module name="FinalLocalVariable">
|
||||
<!-- Checks that local variables that never have their values changed are declared final. -->
|
||||
<property name="tokens" value="VARIABLE_DEF"/>
|
||||
<property name="validateEnhancedForLoopVariable" value="true"/>
|
||||
</module>
|
||||
|
||||
<!--
|
||||
|
||||
LENGTH and CODING CHECKS
|
||||
|
||||
-->
|
||||
|
||||
<module name="LineLength">
|
||||
<!-- Checks if a line is too long. -->
|
||||
<property name="max" value="120"/>
|
||||
<property name="severity" value="error"/>
|
||||
|
||||
<!--
|
||||
The default ignore pattern exempts the following elements:
|
||||
- import statements
|
||||
- long URLs inside comments
|
||||
-->
|
||||
|
||||
<property name="ignorePattern"
|
||||
value="${com.puppycrawl.tools.checkstyle.checks.sizes.LineLength.ignorePattern}"
|
||||
default="^(package .*;\s*)|(import .*;\s*)|( *\* *https?://.*)$"/>
|
||||
</module>
|
||||
|
||||
<module name="LeftCurly">
|
||||
<!-- Checks for placement of the left curly brace ('{'). -->
|
||||
<property name="severity" value="warning"/>
|
||||
</module>
|
||||
|
||||
<module name="RightCurly">
|
||||
<!-- Checks right curlies on CATCH, ELSE, and TRY blocks are on
|
||||
the same line. e.g., the following example is fine:
|
||||
<pre>
|
||||
if {
|
||||
...
|
||||
} else
|
||||
</pre>
|
||||
-->
|
||||
<!-- This next example is not fine:
|
||||
<pre>
|
||||
if {
|
||||
...
|
||||
}
|
||||
else
|
||||
</pre>
|
||||
-->
|
||||
<property name="option" value="same"/>
|
||||
<property name="severity" value="warning"/>
|
||||
</module>
|
||||
|
||||
<!-- Checks for braces around if and else blocks -->
|
||||
<module name="NeedBraces">
|
||||
<property name="severity" value="warning"/>
|
||||
<property name="tokens" value="LITERAL_IF, LITERAL_ELSE, LITERAL_FOR, LITERAL_WHILE, LITERAL_DO"/>
|
||||
</module>
|
||||
|
||||
<module name="UpperEll">
|
||||
<!-- Checks that long constants are defined with an upper ell.-->
|
||||
<property name="severity" value="error"/>
|
||||
</module>
|
||||
|
||||
<module name="FallThrough">
|
||||
<!-- Warn about falling through to the next case statement. Similar to
|
||||
javac -Xlint:fallthrough, but the check is suppressed if a single-line comment
|
||||
on the last non-blank line preceding the fallen-into case contains 'fall through' (or
|
||||
some other variants which we don't publicized to promote consistency).
|
||||
-->
|
||||
<property name="reliefPattern"
|
||||
value="fall through|Fall through|fallthru|Fallthru|falls through|Falls through|fallthrough|Fallthrough|No break|NO break|no break|continue on"/>
|
||||
<property name="severity" value="error"/>
|
||||
</module>
|
||||
|
||||
|
||||
<!--
|
||||
|
||||
MODIFIERS CHECKS
|
||||
|
||||
-->
|
||||
|
||||
<module name="ModifierOrder">
|
||||
<!-- Warn if modifier order is inconsistent with JLS3 8.1.1, 8.3.1, and
|
||||
8.4.3. The prescribed order is:
|
||||
public, protected, private, abstract, static, final, transient, volatile,
|
||||
synchronized, native, strictfp
|
||||
-->
|
||||
</module>
|
||||
|
||||
|
||||
<!--
|
||||
|
||||
WHITESPACE CHECKS
|
||||
|
||||
-->
|
||||
|
||||
<module name="WhitespaceAround">
|
||||
<!-- Checks that various tokens are surrounded by whitespace.
|
||||
This includes most binary operators and keywords followed
|
||||
by regular or curly braces.
|
||||
-->
|
||||
<property name="tokens" value="ASSIGN, BAND, BAND_ASSIGN, BOR,
|
||||
BOR_ASSIGN, BSR, BSR_ASSIGN, BXOR, BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN,
|
||||
EQUAL, GE, GT, LAND, LE, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE,
|
||||
LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF, LITERAL_RETURN,
|
||||
LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE, LOR, LT, MINUS,
|
||||
MINUS_ASSIGN, MOD, MOD_ASSIGN, NOT_EQUAL, PLUS, PLUS_ASSIGN, QUESTION,
|
||||
SL, SL_ASSIGN, SR_ASSIGN, STAR, STAR_ASSIGN"/>
|
||||
<property name="severity" value="error"/>
|
||||
</module>
|
||||
|
||||
<module name="WhitespaceAfter">
|
||||
<!-- Checks that commas, semicolons and typecasts are followed by
|
||||
whitespace.
|
||||
-->
|
||||
<property name="tokens" value="COMMA, SEMI, TYPECAST"/>
|
||||
</module>
|
||||
|
||||
<module name="NoWhitespaceAfter">
|
||||
<!-- Checks that there is no whitespace after various unary operators.
|
||||
Linebreaks are allowed.
|
||||
-->
|
||||
<property name="tokens" value="BNOT, DEC, DOT, INC, LNOT, UNARY_MINUS,
|
||||
UNARY_PLUS"/>
|
||||
<property name="allowLineBreaks" value="true"/>
|
||||
<property name="severity" value="error"/>
|
||||
</module>
|
||||
|
||||
<module name="NoWhitespaceBefore">
|
||||
<!-- Checks that there is no whitespace before various unary operators.
|
||||
Linebreaks are allowed.
|
||||
-->
|
||||
<property name="tokens" value="SEMI, DOT, POST_DEC, POST_INC"/>
|
||||
<property name="allowLineBreaks" value="true"/>
|
||||
<property name="severity" value="error"/>
|
||||
</module>
|
||||
|
||||
<module name="ParenPad">
|
||||
<!-- Checks that there is no whitespace before close parens or after
|
||||
open parens.
|
||||
-->
|
||||
<property name="severity" value="warning"/>
|
||||
</module>
|
||||
|
||||
</module>
|
||||
</module>
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<FindBugsFilter>
|
||||
<Class name="com.microsoft.azure.spring.data.cosmosdb.documentdb.common.GetHashMac"/>
|
||||
<Bug pattern="NP_NONNULL_PARAM_VIOLATION"/>
|
||||
<Bug pattern="Unwritten field"/>
|
||||
<Bug pattern="SIC_INNER_SHOULD_BE_STATIC_ANON"/>
|
||||
|
||||
<Bug pattern="SIC_INNER_SHOULD_BE_STATIC_NEEDS_THIS"/>
|
||||
|
||||
<Bug pattern="UUF_UNUSED_PUBLIC_OR_PROTECTED_FIELD"/>
|
||||
|
||||
</FindBugsFilter>
|
|
@ -0,0 +1,225 @@
|
|||
#!/bin/sh
|
||||
# ----------------------------------------------------------------------------
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Maven2 Start Up Batch script
|
||||
#
|
||||
# Required ENV vars:
|
||||
# ------------------
|
||||
# JAVA_HOME - location of a JDK home dir
|
||||
#
|
||||
# Optional ENV vars
|
||||
# -----------------
|
||||
# M2_HOME - location of maven2's installed home dir
|
||||
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
# e.g. to debug Maven itself, use
|
||||
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
if [ -z "$MAVEN_SKIP_RC" ] ; then
|
||||
|
||||
if [ -f /etc/mavenrc ] ; then
|
||||
. /etc/mavenrc
|
||||
fi
|
||||
|
||||
if [ -f "$HOME/.mavenrc" ] ; then
|
||||
. "$HOME/.mavenrc"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
# OS specific support. $var _must_ be set to either true or false.
|
||||
cygwin=false;
|
||||
darwin=false;
|
||||
mingw=false
|
||||
case "`uname`" in
|
||||
CYGWIN*) cygwin=true ;;
|
||||
MINGW*) mingw=true;;
|
||||
Darwin*) darwin=true
|
||||
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
|
||||
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
if [ -x "/usr/libexec/java_home" ]; then
|
||||
export JAVA_HOME="`/usr/libexec/java_home`"
|
||||
else
|
||||
export JAVA_HOME="/Library/Java/Home"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then
|
||||
if [ -r /etc/gentoo-release ] ; then
|
||||
JAVA_HOME=`java-config --jre-home`
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$M2_HOME" ] ; then
|
||||
## resolve links - $0 may be a link to maven's home
|
||||
PRG="$0"
|
||||
|
||||
# need this for relative symlinks
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG="`dirname "$PRG"`/$link"
|
||||
fi
|
||||
done
|
||||
|
||||
saveddir=`pwd`
|
||||
|
||||
M2_HOME=`dirname "$PRG"`/..
|
||||
|
||||
# make it fully qualified
|
||||
M2_HOME=`cd "$M2_HOME" && pwd`
|
||||
|
||||
cd "$saveddir"
|
||||
# echo Using m2 at $M2_HOME
|
||||
fi
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
||||
if $cygwin ; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME=`cygpath --unix "$M2_HOME"`
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||
[ -n "$CLASSPATH" ] &&
|
||||
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
|
||||
fi
|
||||
|
||||
# For Migwn, ensure paths are in UNIX format before anything is touched
|
||||
if $mingw ; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME="`(cd "$M2_HOME"; pwd)`"
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
|
||||
# TODO classpath?
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
javaExecutable="`which javac`"
|
||||
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
|
||||
# readlink(1) is not available as standard on Solaris 10.
|
||||
readLink=`which readlink`
|
||||
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
|
||||
if $darwin ; then
|
||||
javaHome="`dirname \"$javaExecutable\"`"
|
||||
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
|
||||
else
|
||||
javaExecutable="`readlink -f \"$javaExecutable\"`"
|
||||
fi
|
||||
javaHome="`dirname \"$javaExecutable\"`"
|
||||
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
|
||||
JAVA_HOME="$javaHome"
|
||||
export JAVA_HOME
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$JAVACMD" ] ; then
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
else
|
||||
JAVACMD="`which java`"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
echo "Error: JAVA_HOME is not defined correctly." >&2
|
||||
echo " We cannot execute $JAVACMD" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then
|
||||
echo "Warning: JAVA_HOME environment variable is not set."
|
||||
fi
|
||||
|
||||
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
|
||||
|
||||
# traverses directory structure from process work directory to filesystem root
|
||||
# first directory with .mvn subdirectory is considered project base directory
|
||||
find_maven_basedir() {
|
||||
|
||||
if [ -z "$1" ]
|
||||
then
|
||||
echo "Path not specified to find_maven_basedir"
|
||||
return 1
|
||||
fi
|
||||
|
||||
basedir="$1"
|
||||
wdir="$1"
|
||||
while [ "$wdir" != '/' ] ; do
|
||||
if [ -d "$wdir"/.mvn ] ; then
|
||||
basedir=$wdir
|
||||
break
|
||||
fi
|
||||
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
|
||||
if [ -d "${wdir}" ]; then
|
||||
wdir=`cd "$wdir/.."; pwd`
|
||||
fi
|
||||
# end of workaround
|
||||
done
|
||||
echo "${basedir}"
|
||||
}
|
||||
|
||||
# concatenates all lines of a file
|
||||
concat_lines() {
|
||||
if [ -f "$1" ]; then
|
||||
echo "$(tr -s '\n' ' ' < "$1")"
|
||||
fi
|
||||
}
|
||||
|
||||
BASE_DIR=`find_maven_basedir "$(pwd)"`
|
||||
if [ -z "$BASE_DIR" ]; then
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
|
||||
echo $MAVEN_PROJECTBASEDIR
|
||||
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME=`cygpath --path --windows "$M2_HOME"`
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
|
||||
[ -n "$CLASSPATH" ] &&
|
||||
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
|
||||
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
|
||||
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
|
||||
fi
|
||||
|
||||
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
exec "$JAVACMD" \
|
||||
$MAVEN_OPTS \
|
||||
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
||||
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
||||
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
|
|
@ -0,0 +1,143 @@
|
|||
@REM ----------------------------------------------------------------------------
|
||||
@REM Licensed to the Apache Software Foundation (ASF) under one
|
||||
@REM or more contributor license agreements. See the NOTICE file
|
||||
@REM distributed with this work for additional information
|
||||
@REM regarding copyright ownership. The ASF licenses this file
|
||||
@REM to you under the Apache License, Version 2.0 (the
|
||||
@REM "License"); you may not use this file except in compliance
|
||||
@REM with the License. You may obtain a copy of the License at
|
||||
@REM
|
||||
@REM http://www.apache.org/licenses/LICENSE-2.0
|
||||
@REM
|
||||
@REM Unless required by applicable law or agreed to in writing,
|
||||
@REM software distributed under the License is distributed on an
|
||||
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
@REM KIND, either express or implied. See the License for the
|
||||
@REM specific language governing permissions and limitations
|
||||
@REM under the License.
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Maven2 Start Up Batch script
|
||||
@REM
|
||||
@REM Required ENV vars:
|
||||
@REM JAVA_HOME - location of a JDK home dir
|
||||
@REM
|
||||
@REM Optional ENV vars
|
||||
@REM M2_HOME - location of maven2's installed home dir
|
||||
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
||||
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
|
||||
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
@REM e.g. to debug Maven itself, use
|
||||
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
|
||||
@echo off
|
||||
@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
|
||||
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
||||
|
||||
@REM set %HOME% to equivalent of $HOME
|
||||
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
||||
|
||||
@REM Execute a user defined script before this one
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
|
||||
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
|
||||
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
|
||||
:skipRcPre
|
||||
|
||||
@setlocal
|
||||
|
||||
set ERROR_CODE=0
|
||||
|
||||
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
||||
@setlocal
|
||||
|
||||
@REM ==== START VALIDATION ====
|
||||
if not "%JAVA_HOME%" == "" goto OkJHome
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME not found in your environment. >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
:OkJHome
|
||||
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME is set to an invalid directory. >&2
|
||||
echo JAVA_HOME = "%JAVA_HOME%" >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
@REM ==== END VALIDATION ====
|
||||
|
||||
:init
|
||||
|
||||
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
||||
@REM Fallback to current working directory if not found.
|
||||
|
||||
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
||||
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
|
||||
|
||||
set EXEC_DIR=%CD%
|
||||
set WDIR=%EXEC_DIR%
|
||||
:findBaseDir
|
||||
IF EXIST "%WDIR%"\.mvn goto baseDirFound
|
||||
cd ..
|
||||
IF "%WDIR%"=="%CD%" goto baseDirNotFound
|
||||
set WDIR=%CD%
|
||||
goto findBaseDir
|
||||
|
||||
:baseDirFound
|
||||
set MAVEN_PROJECTBASEDIR=%WDIR%
|
||||
cd "%EXEC_DIR%"
|
||||
goto endDetectBaseDir
|
||||
|
||||
:baseDirNotFound
|
||||
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
||||
cd "%EXEC_DIR%"
|
||||
|
||||
:endDetectBaseDir
|
||||
|
||||
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
||||
|
||||
@setlocal EnableExtensions EnableDelayedExpansion
|
||||
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
||||
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
||||
|
||||
:endReadAdditionalConfig
|
||||
|
||||
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
||||
|
||||
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
|
||||
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
|
||||
if ERRORLEVEL 1 goto error
|
||||
goto end
|
||||
|
||||
:error
|
||||
set ERROR_CODE=1
|
||||
|
||||
:end
|
||||
@endlocal & set ERROR_CODE=%ERROR_CODE%
|
||||
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
|
||||
@REM check for post script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
|
||||
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
|
||||
:skipRcPost
|
||||
|
||||
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
||||
if "%MAVEN_BATCH_PAUSE%" == "on" pause
|
||||
|
||||
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
|
||||
|
||||
exit /B %ERROR_CODE%
|
|
@ -0,0 +1,353 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.microsoft.azure</groupId>
|
||||
<artifactId>spring-data-azure-cosmosdb-documentdb</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
|
||||
<name>Spring Data for Azure Cosmos DB DocumentDB API</name>
|
||||
<description>Spring Data for Azure Cosmos DB DocumentDB API</description>
|
||||
<url>https://github.com/Microsoft/spring-data-azure-cosmosdb-documentdb</url>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>MIT</name>
|
||||
<url>https://github.com/Microsoft/spring-data-azure-cosmosdb-documentdb/blob/master/LICENSE</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<id>yungez</id>
|
||||
<name>Yunge Zhu</name>
|
||||
<email>yungez@microsoft.com</email>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<organization>
|
||||
<name>Microsoft</name>
|
||||
<url>https://www.microsoft.com</url>
|
||||
</organization>
|
||||
|
||||
<scm>
|
||||
<connection>scm:git:git://github.com/Microsoft/spring-data-azure-cosmosdb-documentdb.git</connection>
|
||||
<developerConnection>scm:git:ssh://github.com:Microsoft/spring-data-azure-cosmosdb-documentdb.git
|
||||
</developerConnection>
|
||||
<url>https://github.com/Microsoft/spring-data-azure-cosmosdb-documentdb/tree/master</url>
|
||||
</scm>
|
||||
<properties>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
|
||||
<azure.documentdb.version>1.13.0</azure.documentdb.version>
|
||||
<spring.boot.dependencies.version>1.5.4.RELEASE</spring.boot.dependencies.version>
|
||||
<mockito.core.version>2.8.9</mockito.core.version>
|
||||
|
||||
<azure.test.resourcegroup>documentdbtest</azure.test.resourcegroup>
|
||||
<azure.test.dbname>springdocdbtestdb</azure.test.dbname>
|
||||
<skip.integration.tests>true</skip.integration.tests>
|
||||
<test.on.azure>false</test.on.azure>
|
||||
<test.on.emualator>false</test.on.emualator>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<!-- Import dependency management from Spring Boot -->
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-dependencies</artifactId>
|
||||
<version>${spring.boot.dependencies.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<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-beans</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-commons</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-expression</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--<dependency>-->
|
||||
<!--<groupId>com.microsoft.azure</groupId>-->
|
||||
<!--<artifactId>azure-spring-common</artifactId>-->
|
||||
<!--</dependency>-->
|
||||
|
||||
<dependency>
|
||||
<groupId>com.microsoft.azure</groupId>
|
||||
<artifactId>azure-documentdb</artifactId>
|
||||
<version>${azure.documentdb.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>${mockito.core.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.10.4</version>
|
||||
<configuration>
|
||||
<show>private</show>
|
||||
<failOnError>false</failOnError>
|
||||
<sourceFileExcludes>
|
||||
<exclude>
|
||||
com/microsoft/azure/spring/data/documentdb/core/mapping/BasicDocumentDbPersistentProperty.java
|
||||
</exclude>
|
||||
</sourceFileExcludes>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-javadocs</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<additionalparam>${javadoc.opts}</additionalparam>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>2.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<version>2.17</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>validate</id>
|
||||
<phase>validate</phase>
|
||||
<configuration>
|
||||
<configLocation>${project.basedir}/config/checkstyle.xml</configLocation>
|
||||
<encoding>UTF-8</encoding>
|
||||
<consoleOutput>true</consoleOutput>
|
||||
<failsOnError>true</failsOnError>
|
||||
<failOnViolation>true</failOnViolation>
|
||||
<includeTestSourceDirectory>true</includeTestSourceDirectory>
|
||||
</configuration>
|
||||
<goals>
|
||||
<goal>check</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<linkXRef>false</linkXRef>
|
||||
</configuration>
|
||||
<inherited>true</inherited>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>findbugs-maven-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<configuration>
|
||||
<effort>Max</effort>
|
||||
<threshold>Low</threshold>
|
||||
<xmlOutput>true</xmlOutput>
|
||||
<findbugsXmlOutputDirectory>${project.build.directory}/findbugs
|
||||
</findbugsXmlOutputDirectory>
|
||||
<excludeFilterFile>${project.basedir}/config/findbugs-exclude.xml</excludeFilterFile>
|
||||
</configuration>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.ant</groupId>
|
||||
<artifactId>ant</artifactId>
|
||||
<version>1.9.4</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>check</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>cobertura-maven-plugin</artifactId>
|
||||
<version>2.7</version>
|
||||
<configuration>
|
||||
<formats>
|
||||
<format>html</format>
|
||||
<format>xml</format>
|
||||
</formats>
|
||||
<check>
|
||||
<haltOnFailure>true</haltOnFailure>
|
||||
<branchRate>60</branchRate>
|
||||
<totalBranchRate>60</totalBranchRate>
|
||||
</check>
|
||||
<instrumentation>
|
||||
<excludes>
|
||||
<exclude>com/microsoft/azure/**/GetHashMac.class</exclude>
|
||||
<exclude>com/microsoft/azure/**/Constants.class</exclude>
|
||||
</excludes>
|
||||
</instrumentation>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<version>2.19</version>
|
||||
<configuration>
|
||||
<systemPropertiesFile>src/test/resources/application.properties</systemPropertiesFile>
|
||||
<skipITs>${skip.integration.tests}</skipITs>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>integration-test</id>
|
||||
<goals>
|
||||
<goal>integration-test</goal>
|
||||
<goal>verify</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<version>1.8</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>setup</id>
|
||||
<phase>pre-integration-test</phase>
|
||||
<goals>
|
||||
<goal>run</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<target if="${test.on.azure}">
|
||||
<ant antfile="build.xml" target="setup">
|
||||
</ant>
|
||||
</target>
|
||||
</configuration>
|
||||
</execution>
|
||||
|
||||
<execution>
|
||||
<id>cleanup</id>
|
||||
<phase>post-integration-test</phase>
|
||||
<goals>
|
||||
<goal>run</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<target if="${test.on.azure}">
|
||||
<ant antfile="build.xml" target="cleanup"/>
|
||||
</target>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>dev</id>
|
||||
<activation>
|
||||
<activeByDefault>true</activeByDefault>
|
||||
</activation>
|
||||
<properties>
|
||||
<build.profile.id>dev</build.profile.id>
|
||||
<skip.integration.tests>true</skip.integration.tests>
|
||||
<test.on.azure>false</test.on.azure>
|
||||
<test.on.emulator>false</test.on.emulator>
|
||||
</properties>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>integration-test-azure</id>
|
||||
<properties>
|
||||
<build.profile.id>integration-test-azure</build.profile.id>
|
||||
<skip.integration.tests>false</skip.integration.tests>
|
||||
<test.on.azure>true</test.on.azure>
|
||||
<test.on.emulator>false</test.on.emulator>
|
||||
</properties>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>integration-test-emulator</id>
|
||||
<properties>
|
||||
<build.profile.id>integration-test-emulator</build.profile.id>
|
||||
<skip.integration.tests>false</skip.integration.tests>
|
||||
<test.on.azure>false</test.on.azure>
|
||||
<test.on.emulator>true</test.on.emulator>
|
||||
</properties>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>doclint-java8-disable</id>
|
||||
<activation>
|
||||
<jdk>[1.8,)</jdk>
|
||||
</activation>
|
||||
<properties>
|
||||
<javadoc.opts>-Xdoclint:none</javadoc.opts>
|
||||
</properties>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
|
@ -0,0 +1,132 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>1.5.4.RELEASE</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
<groupId>com.microsoft.azure</groupId>
|
||||
<artifactId>spring-data-azure-cosmodb-documentdb-sample</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Spring Data Azure Cosmos DB DocumentDB Sample</name>
|
||||
<description>Sample project for Spring Data Azure Cosmos DB DocumentDB</description>
|
||||
<url>https://github.com/Microsoft/spring-data-azure-cosmosdb-documentdb</url>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>MIT</name>
|
||||
<url>https://github.com/Microsoft/spring-data-azure-cosmosdb-documentdb/blob/master/LICENSE</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<id>yungez</id>
|
||||
<name>yunge zhu</name>
|
||||
<email>yungez@microsoft.com</email>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<scm>
|
||||
<connection>scm:git:git://github.com/Microsoft/spring-data-azure-cosmosdb-documentdb.git</connection>
|
||||
<developerConnection>scm:git:ssh://github.com:Microsoft/spring-data-azure-cosmosdb-documentdb.git</developerConnection>
|
||||
<url>https://github.com/Microsoft/spring-data-azure-cosmosdb-documentdb/tree/master</url>
|
||||
</scm>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<spring.data.azure.cosmosdb.documentdb.version>0.1.0-SNAPSHOT</spring.data.azure.cosmosdb.documentdb.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.microsoft.azure</groupId>
|
||||
<artifactId>spring-data-azure-cosmosdb-documentdb</artifactId>
|
||||
<version>${spring.data.azure.cosmosdb.documentdb.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<version>2.17</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>validate</id>
|
||||
<phase>validate</phase>
|
||||
<configuration>
|
||||
<configLocation>${project.basedir}/../config/checkstyle.xml</configLocation>
|
||||
<encoding>UTF-8</encoding>
|
||||
<consoleOutput>true</consoleOutput>
|
||||
<failsOnError>true</failsOnError>
|
||||
<failOnViolation>true</failOnViolation>
|
||||
<includeTestSourceDirectory>true</includeTestSourceDirectory>
|
||||
</configuration>
|
||||
<goals>
|
||||
<goal>check</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<linkXRef>false</linkXRef>
|
||||
</configuration>
|
||||
<inherited>true</inherited>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>findbugs-maven-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<configuration>
|
||||
<effort>Max</effort>
|
||||
<threshold>Low</threshold>
|
||||
<xmlOutput>true</xmlOutput>
|
||||
<findbugsXmlOutputDirectory>${project.build.directory}/findbugs
|
||||
</findbugsXmlOutputDirectory>
|
||||
<excludeFilterFile>${project.basedir}/../config/findbugs-exclude.xml</excludeFilterFile>
|
||||
</configuration>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.ant</groupId>
|
||||
<artifactId>ant</artifactId>
|
||||
<version>1.9.4</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>check</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,37 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.sample;
|
||||
|
||||
import com.microsoft.azure.documentdb.ConnectionPolicy;
|
||||
import com.microsoft.azure.documentdb.ConsistencyLevel;
|
||||
import com.microsoft.azure.documentdb.DocumentClient;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.config.AbstractDocumentDbConfiguration;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.repository.config.EnableDocumentDbRepositories;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@EnableDocumentDbRepositories
|
||||
public class AppConfiguration extends AbstractDocumentDbConfiguration {
|
||||
|
||||
@Value("${azure.documentdb.uri}")
|
||||
private String uri;
|
||||
|
||||
@Value("${azure.documentdb.key}")
|
||||
private String key;
|
||||
|
||||
@Value("${azure.documentdb.database}")
|
||||
private String dbName;
|
||||
|
||||
public DocumentClient documentClient() {
|
||||
return new DocumentClient(uri, key, ConnectionPolicy.GetDefault(), ConsistencyLevel.Session);
|
||||
}
|
||||
|
||||
public String getDatabase() {
|
||||
return dbName;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.sample;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@SpringBootApplication
|
||||
public class SampleApplication implements CommandLineRunner {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(SampleApplication.class);
|
||||
|
||||
@Autowired
|
||||
private UserRepository repository;
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SampleApplication.class, args);
|
||||
}
|
||||
|
||||
public void run(String... var1) throws Exception {
|
||||
|
||||
final User testUser = new User("test@test.com", "testFirstName", "testLastName");
|
||||
|
||||
repository.deleteAll();
|
||||
repository.save(testUser);
|
||||
|
||||
final User result = repository.findOne(testUser.getEmailAddress(), testUser.getLastName());
|
||||
|
||||
Assert.state(result.getFirstName().equals(testUser.getFirstName()), "query result firstName doesn't match!");
|
||||
Assert.state(result.getLastName().equals(testUser.getLastName()), "query result lastName doesn't match!");
|
||||
|
||||
LOGGER.info("findOne in User collection get result: {}", result.toString());
|
||||
System.out.println("findOne in User collection get result:" + result.toString());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.sample;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.core.mapping.Document;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.core.mapping.PartitionKey;
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
@Document(collection = "mycollection")
|
||||
public class User {
|
||||
@Id
|
||||
private String emailAddress;
|
||||
private String firstName;
|
||||
@PartitionKey
|
||||
private String lastName;
|
||||
|
||||
public User(String emailAddress, String firstName, String lastName) {
|
||||
this.emailAddress = emailAddress;
|
||||
this.firstName = firstName;
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
public String getEmailAddress() {
|
||||
return emailAddress;
|
||||
}
|
||||
|
||||
public void setEmailAddress(String emailAddress) {
|
||||
this.emailAddress = emailAddress;
|
||||
}
|
||||
|
||||
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
||||
public void setFirstName(String firstName) {
|
||||
this.firstName = firstName;
|
||||
}
|
||||
|
||||
public String getLastName() {
|
||||
return lastName;
|
||||
}
|
||||
|
||||
public void setLastName(String lastName) {
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s: %s %s", emailAddress, firstName, lastName);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.sample;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.repository.DocumentDbRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface UserRepository extends DocumentDbRepository<User, String> {
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
azure.documentdb.uri=put-your-documentdb-uri-here
|
||||
azure.documentdb.key=put-your-documentdb-key-here
|
||||
azure.documentdb.database=put-your-documentdb-databasename-here
|
|
@ -0,0 +1,31 @@
|
|||
@echo off
|
||||
rem cleanup test resource
|
||||
|
||||
set clientId=%CLIENT_ID%
|
||||
set clientKey=%CLIENT_KEY%
|
||||
set tenantId=%TENANT_ID%
|
||||
|
||||
if "%clientId%" == "" (
|
||||
goto :end
|
||||
)
|
||||
if "%clientKey%" == "" (
|
||||
goto :end
|
||||
)
|
||||
if "%tenantId%" == "" (
|
||||
goto :end
|
||||
)
|
||||
|
||||
set resourcegroup=%1
|
||||
set dbname=%2
|
||||
|
||||
if "%resourcegroup" == "" (
|
||||
goto :end
|
||||
)
|
||||
if "%dbname" == "" (
|
||||
goto :end
|
||||
)
|
||||
|
||||
call az login --service-principal -u %clientId% -p %clientKey% --tenant %tenantId% >> tmp.txt
|
||||
call az cosmosdb delete --name %dbname% --resource-group %resourcegroup%
|
||||
|
||||
:end
|
|
@ -0,0 +1,17 @@
|
|||
# cleanup test resources
|
||||
#!/bin/bash
|
||||
resourcegroup=$1
|
||||
dbname=$2
|
||||
|
||||
if [ "$CLIENT_ID" == "" ]; then
|
||||
exit 0
|
||||
fi
|
||||
if [ "$CLIENT_KEY" == "" ]; then
|
||||
exit 0
|
||||
fi
|
||||
if [ "$TENANT_ID" == "" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
az login --service-principal -u $CLIENT_ID -p $CLIENT_KEY --tenant $TENANT_ID >> tmp.txt
|
||||
az cosmosdb delete --name $dbname --resource-group $resourcegroup
|
|
@ -0,0 +1,41 @@
|
|||
@echo off
|
||||
set clientId=%CLIENT_ID%
|
||||
set clientKey=%CLIENT_KEY%
|
||||
set tenantId=%TENANT_ID%
|
||||
|
||||
if "%clientId%" == "" (
|
||||
goto :noSetup
|
||||
)
|
||||
if "%clientKey%" == "" (
|
||||
goto :noSetup
|
||||
)
|
||||
if "%tenantId%" == "" (
|
||||
goto :noSetup
|
||||
)
|
||||
|
||||
set resourcegroup=%1
|
||||
set dbname=%2
|
||||
|
||||
if "%resourcegroup" == "" (
|
||||
goto :noSetup
|
||||
)
|
||||
if "%dbname" == "" (
|
||||
goto :noSetup
|
||||
)
|
||||
|
||||
call az login --service-principal -u %clientId% -p %clientKey% --tenant %tenantId% >> null
|
||||
set createcmd='az cosmosdb create --name %dbname% --resource-group %resourcegroup% --kind GlobalDocumentDB --query documentEndpoint'
|
||||
|
||||
for /f "tokens=*" %%a in (%createcmd%) do (set documentdburi=%%a)
|
||||
|
||||
set listcmd='az cosmosdb list-keys --name %dbname% --resource-group %resourcegroup% --query primaryMasterKey'
|
||||
for /f "tokens=*" %%a in (%listcmd%) do (set documentdbkey=%%a)
|
||||
echo %documentdbkey%
|
||||
|
||||
goto :end
|
||||
|
||||
:noSetup
|
||||
echo not to setup test resources
|
||||
exit 0
|
||||
|
||||
:end
|
|
@ -0,0 +1,20 @@
|
|||
# setup test resources
|
||||
#!/bin/bash
|
||||
resourcegroup=$1
|
||||
dbname=$2
|
||||
|
||||
if [ -z "$CLIENT_ID" ]; then
|
||||
exit 0
|
||||
fi
|
||||
if [ -z "$CLIENT_KEY" ]; then
|
||||
exit 0
|
||||
fi
|
||||
if [ -z "$TENANT_ID" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
az login --service-principal -u $CLIENT_ID -p $CLIENT_KEY --tenant $TENANT_ID >> tmp.txt
|
||||
documentDbUri=$(az cosmosdb create --name $dbname --resource-group $resourcegroup --kind GlobalDocumentDB --query documentEndpoint)
|
||||
documentDbKey=$(az cosmosdb list-keys --name $dbname --resource-group $resourcegroup --query primaryMasterKey)
|
||||
|
||||
echo $documentDbKey
|
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb;
|
||||
|
||||
import com.microsoft.azure.documentdb.ConnectionPolicy;
|
||||
import com.microsoft.azure.documentdb.ConsistencyLevel;
|
||||
import com.microsoft.azure.documentdb.DocumentClient;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.common.GetHashMac;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
public class DocumentDbFactory {
|
||||
|
||||
private static final String USER_AGENT_SUFFIX = "spring-data/0.1.8-SNAPSHOT";
|
||||
|
||||
private DocumentClient documentClient;
|
||||
|
||||
public DocumentDbFactory(String host, String key) {
|
||||
this(host, key, true);
|
||||
}
|
||||
|
||||
public DocumentDbFactory(String host, String key, boolean isBiEnabled) {
|
||||
Assert.hasText(host, "host must not be empty!");
|
||||
Assert.hasText(key, "key must not be empty!");
|
||||
|
||||
final ConnectionPolicy policy = ConnectionPolicy.GetDefault();
|
||||
|
||||
String userAgent = ";" + USER_AGENT_SUFFIX;
|
||||
if (isBiEnabled && GetHashMac.getHashMac() != null) {
|
||||
userAgent += ";" + GetHashMac.getHashMac();
|
||||
}
|
||||
policy.setUserAgentSuffix(userAgent);
|
||||
|
||||
documentClient = new DocumentClient(host, key, policy, ConsistencyLevel.Session);
|
||||
}
|
||||
|
||||
public DocumentDbFactory(DocumentClient client) {
|
||||
this.documentClient = client;
|
||||
}
|
||||
|
||||
public DocumentClient getDocumentClient() {
|
||||
return documentClient;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
/*
|
||||
* Disclaimer:
|
||||
* This class is copied from https://github.com/Microsoft/azure-tools-for-java/ with minor modification (fixing
|
||||
* static analysis error).
|
||||
* Location in the repo: /Utils/azuretools-core/src/com/microsoft/azuretools/azurecommons/util/GetHashMac.java
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.common;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class GetHashMac {
|
||||
public static final String MAC_REGEX = "([0-9A-Fa-f]{2}[:-]){5}[0-9A-Fa-f]{2}";
|
||||
public static final String MAC_REGEX_ZERO = "([0]{2}[:-]){5}[0]{2}";
|
||||
public static final String HASHED_MAC_REGEX = "[0-9a-f]{64}";
|
||||
|
||||
private GetHashMac() {
|
||||
super();
|
||||
}
|
||||
|
||||
public static boolean isValidHashMacFormat(String hashMac) {
|
||||
if (hashMac == null || hashMac.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final Pattern hashedMacPattern = Pattern.compile(HASHED_MAC_REGEX);
|
||||
final Matcher matcher = hashedMacPattern.matcher(hashMac);
|
||||
return matcher.matches();
|
||||
}
|
||||
|
||||
public static String getHashMac() {
|
||||
final String rawMac = getRawMac();
|
||||
if (rawMac == null || rawMac.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final Pattern pattern = Pattern.compile(MAC_REGEX);
|
||||
final Pattern patternZero = Pattern.compile(MAC_REGEX_ZERO);
|
||||
final Matcher matcher = pattern.matcher(rawMac);
|
||||
String mac = "";
|
||||
while (matcher.find()) {
|
||||
mac = matcher.group(0);
|
||||
if (!patternZero.matcher(mac).matches()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return hash(mac);
|
||||
}
|
||||
|
||||
private static String getRawMac() {
|
||||
final StringBuilder ret = new StringBuilder();
|
||||
|
||||
final String os = System.getProperty("os.name");
|
||||
String[] command = {"ifconfig", "-a"};
|
||||
if (os != null && !os.isEmpty() && os.toLowerCase().startsWith("win")) {
|
||||
command = new String[]{"getmac"};
|
||||
}
|
||||
|
||||
try {
|
||||
final ProcessBuilder builder = new ProcessBuilder(command);
|
||||
final Process process = builder.start();
|
||||
try (final InputStream inputStream = process.getInputStream();
|
||||
final InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
|
||||
final BufferedReader br = new BufferedReader(inputStreamReader)) {
|
||||
String tmp;
|
||||
while ((tmp = br.readLine()) != null) {
|
||||
ret.append(tmp);
|
||||
}
|
||||
|
||||
}
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return ret.toString();
|
||||
}
|
||||
|
||||
private static String hash(String mac) {
|
||||
if (mac == null || mac.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final String ret;
|
||||
try {
|
||||
final MessageDigest md = MessageDigest.getInstance("SHA-256");
|
||||
final byte[] bytes = mac.getBytes("UTF-8");
|
||||
md.update(bytes);
|
||||
final byte[] bytesAfterDigest = md.digest();
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < bytesAfterDigest.length; i++) {
|
||||
sb.append(Integer.toString((bytesAfterDigest[i] & 0xff) + 0x100, 16).substring(1));
|
||||
}
|
||||
|
||||
ret = sb.toString();
|
||||
} catch (NoSuchAlgorithmException | UnsupportedEncodingException ex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.config;
|
||||
|
||||
import com.microsoft.azure.documentdb.DocumentClient;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.DocumentDbFactory;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.core.DocumentDbTemplate;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.core.convert.MappingDocumentDbConverter;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public abstract class AbstractDocumentDbConfiguration extends DocumentDbConfigurationSupport {
|
||||
|
||||
public abstract String getDatabase();
|
||||
|
||||
public abstract DocumentClient documentClient();
|
||||
|
||||
@Bean
|
||||
public DocumentDbFactory documentDbFactory() throws Exception {
|
||||
return new DocumentDbFactory(this.documentClient());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DocumentDbTemplate documentDbTemplate() throws Exception {
|
||||
return new DocumentDbTemplate(this.documentDbFactory(), this.mappingDocumentDbConverter(), this.getDatabase());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MappingDocumentDbConverter mappingDocumentDbConverter() throws Exception {
|
||||
return new MappingDocumentDbConverter(this.documentDbMappingContext());
|
||||
}
|
||||
|
||||
protected String getMappingBasePackage() {
|
||||
final Package mappingBasePackage = getClass().getPackage();
|
||||
return mappingBasePackage == null ? null : mappingBasePackage.getName();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.config;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.core.mapping.DocumentDbMappingContext;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
import org.springframework.data.annotation.Persistent;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mapping.context.MappingContextIsNewStrategyFactory;
|
||||
import org.springframework.data.mapping.context.PersistentEntities;
|
||||
import org.springframework.data.support.CachingIsNewStrategyFactory;
|
||||
import org.springframework.data.support.IsNewStrategyFactory;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
||||
public abstract class DocumentDbConfigurationSupport {
|
||||
@Bean
|
||||
public DocumentDbMappingContext documentDbMappingContext() throws ClassNotFoundException {
|
||||
final DocumentDbMappingContext mappingContext = new DocumentDbMappingContext();
|
||||
mappingContext.setInitialEntitySet(getInitialEntitySet());
|
||||
|
||||
return mappingContext;
|
||||
}
|
||||
|
||||
protected Collection<String> getMappingBasePackages() {
|
||||
final Package mappingBasePackage = getClass().getPackage();
|
||||
return Collections.singleton(mappingBasePackage == null ? null : mappingBasePackage.getName());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public IsNewStrategyFactory isNewStrategyFactory() throws ClassNotFoundException {
|
||||
return new CachingIsNewStrategyFactory(new MappingContextIsNewStrategyFactory(
|
||||
new PersistentEntities(Arrays.<MappingContext<?, ?>>asList(
|
||||
new MappingContext[]{documentDbMappingContext()}))));
|
||||
}
|
||||
|
||||
protected Set<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
|
||||
final Set<Class<?>> initialEntitySet = new HashSet<Class<?>>();
|
||||
|
||||
for (final String basePackage : getMappingBasePackages()) {
|
||||
initialEntitySet.addAll(scanForEntities(basePackage));
|
||||
}
|
||||
|
||||
return initialEntitySet;
|
||||
}
|
||||
|
||||
protected Set<Class<?>> scanForEntities(String basePackage) throws ClassNotFoundException {
|
||||
if (!StringUtils.hasText(basePackage)) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
final Set<Class<?>> initialEntitySet = new HashSet<Class<?>>();
|
||||
|
||||
if (StringUtils.hasText(basePackage)) {
|
||||
final ClassPathScanningCandidateComponentProvider componentProvider =
|
||||
new ClassPathScanningCandidateComponentProvider(false);
|
||||
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Persistent.class));
|
||||
|
||||
for (final BeanDefinition candidate : componentProvider.findCandidateComponents(basePackage)) {
|
||||
|
||||
initialEntitySet
|
||||
.add(ClassUtils.forName(candidate.getBeanClassName(),
|
||||
DocumentDbConfigurationSupport.class.getClassLoader()));
|
||||
}
|
||||
}
|
||||
|
||||
return initialEntitySet;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.core;
|
||||
|
||||
import com.microsoft.azure.documentdb.DocumentCollection;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface DocumentDbOperations {
|
||||
|
||||
String getCollectionName(Class<?> entityClass);
|
||||
|
||||
DocumentCollection createCollectionIfNotExists(String collectionName,
|
||||
String partitionKeyFieldName,
|
||||
Integer requestUnit);
|
||||
|
||||
<T> List<T> findAll(Class<T> entityClass,
|
||||
String partitionKeyFieldName,
|
||||
String partitionKeyFieldValue);
|
||||
|
||||
<T> List<T> findAll(String collectionName,
|
||||
Class<T> entityClass,
|
||||
String partitionKeyFieldName,
|
||||
String partitionKeyFieldValue);
|
||||
|
||||
<T> T findById(Object id,
|
||||
Class<T> entityClass,
|
||||
String partitionKeyFieldValue);
|
||||
|
||||
<T> T findById(String collectionName,
|
||||
Object id,
|
||||
Class<T> entityClass,
|
||||
String partitionKeyFieldValue);
|
||||
|
||||
<T> T insert(T objectToSave, String partitionKeyFieldValue);
|
||||
|
||||
<T> T insert(String collectionName,
|
||||
T objectToSave,
|
||||
String partitionKeyFieldValue);
|
||||
|
||||
<T> void update(T object, String id, String partitionKeyFieldValue);
|
||||
|
||||
<T> void update(String collectionName,
|
||||
T object,
|
||||
String id,
|
||||
String partitionKeyFieldValue);
|
||||
|
||||
<T> void deleteById(String collectionName,
|
||||
Object id,
|
||||
Class<T> domainClass,
|
||||
String partitionKeyFieldValue);
|
||||
|
||||
void deleteAll(String collectionName);
|
||||
}
|
|
@ -0,0 +1,376 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.core;
|
||||
|
||||
import com.microsoft.azure.documentdb.*;
|
||||
import com.microsoft.azure.documentdb.internal.HttpConstants;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.DocumentDbFactory;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.core.convert.MappingDocumentDbConverter;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.core.mapping.DocumentDbPersistentEntity;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.core.mapping.DocumentDbPersistentProperty;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class DocumentDbTemplate implements DocumentDbOperations, ApplicationContextAware {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DocumentDbTemplate.class);
|
||||
|
||||
private final DocumentDbFactory documentDbFactory;
|
||||
private final MappingDocumentDbConverter mappingDocumentDbConverter;
|
||||
private final String databaseName;
|
||||
private final MappingContext<? extends DocumentDbPersistentEntity<?>, DocumentDbPersistentProperty> mappingContext;
|
||||
|
||||
private Database databaseCache;
|
||||
private List<String> collectionCache;
|
||||
|
||||
public DocumentDbTemplate(DocumentDbFactory documentDbFactory,
|
||||
MappingDocumentDbConverter mappingDocumentDbConverter,
|
||||
String dbName) {
|
||||
Assert.notNull(documentDbFactory, "DocumentDbFactory must not be null!");
|
||||
Assert.notNull(mappingDocumentDbConverter, "MappingDocumentDbConverter must not be null!");
|
||||
|
||||
this.databaseName = dbName;
|
||||
this.documentDbFactory = documentDbFactory;
|
||||
this.mappingDocumentDbConverter = mappingDocumentDbConverter;
|
||||
this.mappingContext = mappingDocumentDbConverter.getMappingContext();
|
||||
this.collectionCache = new ArrayList<>();
|
||||
}
|
||||
|
||||
public DocumentDbTemplate(DocumentClient client,
|
||||
MappingDocumentDbConverter mappingDocumentDbConverter,
|
||||
String dbName) {
|
||||
|
||||
this(new DocumentDbFactory(client), mappingDocumentDbConverter, dbName);
|
||||
}
|
||||
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
}
|
||||
|
||||
public <T> T insert(T objectToSave, String partitionKeyFieldValue) {
|
||||
return insert(getCollectionName(objectToSave.getClass()),
|
||||
objectToSave,
|
||||
partitionKeyFieldValue);
|
||||
}
|
||||
|
||||
|
||||
public <T> T insert(String collectionName,
|
||||
T objectToSave,
|
||||
String partitionKeyFieldValue) {
|
||||
final Document document = new Document();
|
||||
mappingDocumentDbConverter.write(objectToSave, document);
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("execute createDocument in database {} collection {}",
|
||||
this.databaseName, collectionName);
|
||||
}
|
||||
|
||||
try {
|
||||
documentDbFactory.getDocumentClient()
|
||||
.createDocument(getCollectionLink(this.databaseName, collectionName), document,
|
||||
getRequestOptions(partitionKeyFieldValue, null), false);
|
||||
return objectToSave;
|
||||
} catch (DocumentClientException e) {
|
||||
throw new RuntimeException("insert exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
public <T> T findById(Object id,
|
||||
Class<T> entityClass,
|
||||
String partitionKeyFieldValue) {
|
||||
return findById(getCollectionName(entityClass),
|
||||
id,
|
||||
entityClass,
|
||||
partitionKeyFieldValue);
|
||||
}
|
||||
|
||||
public <T> T findById(String collectionName,
|
||||
Object id,
|
||||
Class<T> entityClass,
|
||||
String partitionKeyFieldValue) {
|
||||
|
||||
try {
|
||||
final Resource resource = documentDbFactory.getDocumentClient()
|
||||
.readDocument(getDocumentLink(this.databaseName, collectionName, (String) id),
|
||||
getRequestOptions(partitionKeyFieldValue, null)).getResource();
|
||||
|
||||
if (resource instanceof Document) {
|
||||
final Document document = (Document) resource;
|
||||
return mappingDocumentDbConverter.read(entityClass, document);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (DocumentClientException e) {
|
||||
if (e.getStatusCode() == HttpConstants.StatusCodes.NOTFOUND) {
|
||||
return null;
|
||||
}
|
||||
|
||||
throw new RuntimeException("findById exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
public <T> void update(T object, String id, String partitionKeyFieldValue) {
|
||||
update(getCollectionName(object.getClass()), object, id, partitionKeyFieldValue);
|
||||
}
|
||||
|
||||
|
||||
public <T> void update(String collectionName, T object, String id, String partitionKeyFieldValue) {
|
||||
|
||||
try {
|
||||
final Resource resource = documentDbFactory.getDocumentClient()
|
||||
.readDocument(getDocumentLink(this.databaseName, collectionName, id),
|
||||
getRequestOptions(partitionKeyFieldValue, null))
|
||||
.getResource();
|
||||
|
||||
if (resource instanceof Document) {
|
||||
final Document originalDoc = (Document) resource;
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("execute replaceDocument in database {} collection {} with id {}",
|
||||
this.databaseName, collectionName, id);
|
||||
}
|
||||
|
||||
mappingDocumentDbConverter.write(object, originalDoc);
|
||||
|
||||
documentDbFactory.getDocumentClient().replaceDocument(
|
||||
originalDoc.getSelfLink(),
|
||||
originalDoc,
|
||||
getRequestOptions(partitionKeyFieldValue, null));
|
||||
} else {
|
||||
LOGGER.error("invalid Document to update {}", resource.getSelfLink());
|
||||
throw new RuntimeException("invalid Document to update " + resource.getSelfLink());
|
||||
}
|
||||
} catch (DocumentClientException ex) {
|
||||
throw new RuntimeException("update exception", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public <T> List<T> findAll(Class<T> entityClass,
|
||||
String partitionKeyFieldName,
|
||||
String partitionKeyFieldValue) {
|
||||
return findAll(getCollectionName(entityClass),
|
||||
entityClass,
|
||||
partitionKeyFieldName,
|
||||
partitionKeyFieldValue);
|
||||
}
|
||||
|
||||
|
||||
public <T> List<T> findAll(String collectionName,
|
||||
final Class<T> entityClass,
|
||||
String partitionKeyFieldName,
|
||||
String partitionKeyFieldValue) {
|
||||
final List<DocumentCollection> collections = documentDbFactory.getDocumentClient().
|
||||
queryCollections(
|
||||
getDatabaseLink(this.databaseName),
|
||||
new SqlQuerySpec("SELECT * FROM ROOT r WHERE r.id=@id",
|
||||
new SqlParameterCollection(new SqlParameter("@id", collectionName))), null)
|
||||
.getQueryIterable().toList();
|
||||
|
||||
if (collections.size() != 1) {
|
||||
throw new RuntimeException("expect only one collection: " + collectionName
|
||||
+ " in database: " + this.databaseName + ", but found " + collections.size());
|
||||
}
|
||||
|
||||
SqlQuerySpec sqlQuerySpec = new SqlQuerySpec("SELECT * FROM root c");
|
||||
if (partitionKeyFieldName != null && !partitionKeyFieldName.isEmpty()) {
|
||||
sqlQuerySpec = new SqlQuerySpec("SELECT * FROM root c WHERE c." + partitionKeyFieldName + "=@partition",
|
||||
new SqlParameterCollection(new SqlParameter("@partition", partitionKeyFieldValue)));
|
||||
}
|
||||
|
||||
final FeedOptions feedOptions = new FeedOptions();
|
||||
feedOptions.setEnableCrossPartitionQuery(true);
|
||||
final List<Document> results = documentDbFactory.getDocumentClient()
|
||||
.queryDocuments(collections.get(0).getSelfLink(),
|
||||
sqlQuerySpec, feedOptions)
|
||||
.getQueryIterable().toList();
|
||||
|
||||
final List<T> entities = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < results.size(); i++) {
|
||||
final T entity = mappingDocumentDbConverter.read(entityClass, results.get(i));
|
||||
entities.add(entity);
|
||||
}
|
||||
|
||||
return entities;
|
||||
}
|
||||
|
||||
public void deleteAll(String collectionName) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("execute deleteCollection in database {} collection {} with id {}",
|
||||
this.databaseName, collectionName);
|
||||
}
|
||||
|
||||
try {
|
||||
documentDbFactory.getDocumentClient()
|
||||
.deleteCollection(getCollectionLink(this.databaseName, collectionName), null);
|
||||
if (this.collectionCache.contains(collectionName)) {
|
||||
this.collectionCache.remove(collectionName);
|
||||
}
|
||||
} catch (DocumentClientException ex) {
|
||||
if (ex.getStatusCode() == 404) {
|
||||
LOGGER.warn("deleteAll in database {} collection {} met NOTFOUND error {}",
|
||||
this.databaseName, collectionName, ex.getMessage());
|
||||
} else {
|
||||
throw new RuntimeException("deleteAll exception", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getCollectionName(Class<?> entityClass) {
|
||||
return entityClass.getSimpleName();
|
||||
}
|
||||
|
||||
private Database createDatabaseIfNotExists(String dbName) {
|
||||
try {
|
||||
final List<Database> dbList = documentDbFactory.getDocumentClient()
|
||||
.queryDatabases(new SqlQuerySpec("SELECT * FROM root r WHERE r.id=@id",
|
||||
new SqlParameterCollection(new SqlParameter("@id", dbName))), null)
|
||||
.getQueryIterable().toList();
|
||||
|
||||
if (!dbList.isEmpty()) {
|
||||
return dbList.get(0);
|
||||
} else {
|
||||
// create new database
|
||||
final Database db = new Database();
|
||||
db.setId(dbName);
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("execute createDatabase {}", dbName);
|
||||
}
|
||||
|
||||
final Resource resource = documentDbFactory.getDocumentClient()
|
||||
.createDatabase(db, null).getResource();
|
||||
|
||||
if (resource instanceof Database) {
|
||||
return (Database) resource;
|
||||
} else {
|
||||
LOGGER.error("create database {} get unexpected result: {}" + resource.getSelfLink());
|
||||
throw new RuntimeException("create database {} get unexpected result: " + resource.getSelfLink());
|
||||
}
|
||||
}
|
||||
} catch (DocumentClientException ex) {
|
||||
throw new RuntimeException("createOrGetDatabase exception", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public DocumentCollection createCollection(String collectionName,
|
||||
RequestOptions collectionOptions,
|
||||
String partitionKeyFieldName) {
|
||||
return createCollection(this.databaseName, collectionName, collectionOptions, partitionKeyFieldName);
|
||||
}
|
||||
|
||||
public DocumentCollection createCollection(String dbName,
|
||||
String collectionName,
|
||||
RequestOptions collectionOptions,
|
||||
String partitionKeyFieldName) {
|
||||
DocumentCollection collection = new DocumentCollection();
|
||||
collection.setId(collectionName);
|
||||
|
||||
if (partitionKeyFieldName != null && !partitionKeyFieldName.isEmpty()) {
|
||||
final PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition();
|
||||
final ArrayList<String> paths = new ArrayList<String>();
|
||||
|
||||
paths.add(getPartitionKeyPath(partitionKeyFieldName));
|
||||
partitionKeyDefinition.setPaths(paths);
|
||||
collection.setPartitionKey(partitionKeyDefinition);
|
||||
}
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("execute createCollection in database {} collection {}", dbName, collectionName);
|
||||
}
|
||||
|
||||
try {
|
||||
final Resource resource = documentDbFactory.getDocumentClient()
|
||||
.createCollection(getDatabaseLink(dbName), collection, collectionOptions)
|
||||
.getResource();
|
||||
if (resource instanceof DocumentCollection) {
|
||||
collection = (DocumentCollection) resource;
|
||||
}
|
||||
return collection;
|
||||
} catch (DocumentClientException e) {
|
||||
throw new RuntimeException("createCollection exception", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public DocumentCollection createCollectionIfNotExists(String collectionName,
|
||||
String partitionKeyFieldName,
|
||||
Integer requestUnit) {
|
||||
if (this.databaseCache == null) {
|
||||
this.databaseCache = createDatabaseIfNotExists(this.databaseName);
|
||||
}
|
||||
|
||||
final List<DocumentCollection> collectionList = documentDbFactory.getDocumentClient()
|
||||
.queryCollections(getDatabaseLink(this.databaseName),
|
||||
new SqlQuerySpec("SELECT * FROM root r WHERE r.id=@id",
|
||||
new SqlParameterCollection(new SqlParameter("@id", collectionName))), null)
|
||||
.getQueryIterable().toList();
|
||||
|
||||
if (!collectionList.isEmpty()) {
|
||||
return collectionList.get(0);
|
||||
} else {
|
||||
final RequestOptions requestOptions = getRequestOptions(null, requestUnit);
|
||||
return createCollection(this.databaseName, collectionName, requestOptions, partitionKeyFieldName);
|
||||
}
|
||||
}
|
||||
|
||||
public <T> void deleteById(String collectionName,
|
||||
Object id,
|
||||
Class<T> domainClass,
|
||||
String partitionKeyFieldValue) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("execute deleteById in database {} collection {}", this.databaseName, collectionName);
|
||||
}
|
||||
|
||||
try {
|
||||
documentDbFactory.getDocumentClient().deleteDocument(
|
||||
getDocumentLink(this.databaseName, collectionName, id.toString()),
|
||||
getRequestOptions(partitionKeyFieldValue, null));
|
||||
|
||||
} catch (DocumentClientException ex) {
|
||||
throw new RuntimeException("deleteById exception", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private String getDatabaseLink(String databaseName) {
|
||||
return "dbs/" + databaseName;
|
||||
}
|
||||
|
||||
private String getCollectionLink(String databaseName, String collectionName) {
|
||||
return getDatabaseLink(databaseName) + "/colls/" + collectionName;
|
||||
}
|
||||
|
||||
private String getDocumentLink(String databaseName, String collectionName, String documentId) {
|
||||
return getCollectionLink(databaseName, collectionName) + "/docs/" + documentId;
|
||||
}
|
||||
|
||||
private String getPartitionKeyPath(String partitionKey) {
|
||||
return "/" + partitionKey;
|
||||
}
|
||||
|
||||
private RequestOptions getRequestOptions(String partitionKeyValue, Integer requestUnit) {
|
||||
if ((partitionKeyValue == null || partitionKeyValue.isEmpty()) && requestUnit == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final RequestOptions requestOptions = new RequestOptions();
|
||||
if (!(partitionKeyValue == null || partitionKeyValue.isEmpty())) {
|
||||
requestOptions.setPartitionKey(new PartitionKey(partitionKeyValue));
|
||||
}
|
||||
if (requestUnit != null) {
|
||||
requestOptions.setOfferThroughput(requestUnit);
|
||||
}
|
||||
|
||||
return requestOptions;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.core.convert;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.microsoft.azure.documentdb.Document;
|
||||
|
||||
public class DocumentDbConverter {
|
||||
|
||||
private final Gson gson;
|
||||
|
||||
public DocumentDbConverter() {
|
||||
gson = new Gson();
|
||||
}
|
||||
|
||||
public <T> Document convertToDocument(T entity) {
|
||||
final String json = this.gson.toJson(entity);
|
||||
|
||||
return new Document(json);
|
||||
}
|
||||
|
||||
public <T> T convertFromDocument(Document document, Class<T> entityClass) {
|
||||
return this.gson.fromJson(document.toJson(), entityClass);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,153 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.core.convert;
|
||||
|
||||
import com.microsoft.azure.documentdb.Document;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.core.mapping.DocumentDbPersistentEntity;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.core.mapping.DocumentDbPersistentProperty;
|
||||
import org.apache.commons.lang3.ClassUtils;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.data.convert.EntityConverter;
|
||||
import org.springframework.data.mapping.PersistentPropertyAccessor;
|
||||
import org.springframework.data.mapping.PropertyHandler;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class MappingDocumentDbConverter
|
||||
implements EntityConverter<DocumentDbPersistentEntity<?>, DocumentDbPersistentProperty, Object, Document>,
|
||||
ApplicationContextAware {
|
||||
|
||||
protected final MappingContext<? extends DocumentDbPersistentEntity<?>,
|
||||
DocumentDbPersistentProperty> mappingContext;
|
||||
protected GenericConversionService conversionService;
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
public MappingDocumentDbConverter(
|
||||
MappingContext<? extends DocumentDbPersistentEntity<?>, DocumentDbPersistentProperty> mappingContext) {
|
||||
this.mappingContext = mappingContext;
|
||||
this.conversionService = new GenericConversionService();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R extends Object> R read(Class<R> type, Document sourceDocument) {
|
||||
if (sourceDocument == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final DocumentDbPersistentEntity<?> entity = mappingContext.getPersistentEntity(type);
|
||||
return readInternal(entity, type, sourceDocument);
|
||||
}
|
||||
|
||||
protected <R extends Object> R readInternal(final DocumentDbPersistentEntity<?> entity, Class<R> type,
|
||||
final Document sourceDocument) {
|
||||
final R result = instantiate(type);
|
||||
|
||||
final PersistentPropertyAccessor accessor = entity.getPropertyAccessor(result);
|
||||
|
||||
final DocumentDbPersistentProperty idProperty = entity.getIdProperty();
|
||||
final Object idValue = sourceDocument.getId();
|
||||
|
||||
if (idProperty != null) {
|
||||
accessor.setProperty(idProperty, idValue);
|
||||
}
|
||||
|
||||
entity.doWithProperties((PropertyHandler<DocumentDbPersistentProperty>) prop -> {
|
||||
if (idProperty != null && idProperty.equals(prop)) {
|
||||
return;
|
||||
}
|
||||
accessor.setProperty(prop, sourceDocument.get(prop.getName()));
|
||||
}
|
||||
);
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Object sourceEntity, Document document) {
|
||||
if (sourceEntity == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final DocumentDbPersistentEntity<?> entity = mappingContext.getPersistentEntity(sourceEntity.getClass());
|
||||
writeInternal(sourceEntity, document, entity);
|
||||
}
|
||||
|
||||
public void writeInternal(final Object entity,
|
||||
final Document targetDocument,
|
||||
final DocumentDbPersistentEntity<?> entityInformation) {
|
||||
if (entity == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (entityInformation == null) {
|
||||
throw new MappingException("no mapping metadata for entity type: " + entity.getClass().getName());
|
||||
}
|
||||
|
||||
final ConvertingPropertyAccessor accessor = getPropertyAccessor(entity);
|
||||
final DocumentDbPersistentProperty idProperty = entityInformation.getIdProperty();
|
||||
|
||||
if (idProperty != null) {
|
||||
targetDocument.setId((String) accessor.getProperty(idProperty));
|
||||
}
|
||||
|
||||
for (final Field field : entity.getClass().getDeclaredFields()) {
|
||||
if (null != idProperty && field.getName().equals(idProperty.getName())) {
|
||||
continue;
|
||||
}
|
||||
targetDocument.set(field.getName(),
|
||||
accessor.getProperty(entityInformation.getPersistentProperty(field.getName())));
|
||||
}
|
||||
}
|
||||
|
||||
public ApplicationContext getApplicationContext() {
|
||||
return this.applicationContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConversionService getConversionService() {
|
||||
return conversionService;
|
||||
}
|
||||
|
||||
public MappingContext<? extends DocumentDbPersistentEntity<?>, DocumentDbPersistentProperty> getMappingContext() {
|
||||
return mappingContext;
|
||||
}
|
||||
|
||||
|
||||
private ConvertingPropertyAccessor getPropertyAccessor(Object entity) {
|
||||
final DocumentDbPersistentEntity<?> entityInformation = mappingContext.getPersistentEntity(entity.getClass());
|
||||
final PersistentPropertyAccessor accessor = entityInformation.getPropertyAccessor(entity);
|
||||
return new ConvertingPropertyAccessor(accessor, conversionService);
|
||||
}
|
||||
|
||||
private <T> T instantiate(Class<T> tClass) {
|
||||
try {
|
||||
final Constructor<T> constructor = (Constructor<T>) tClass.getConstructors()[0];
|
||||
final List<Object> params = new ArrayList<>();
|
||||
for (final Class<?> paramType : constructor.getParameterTypes()) {
|
||||
params.add((paramType.isPrimitive()) ? ClassUtils.primitiveToWrapper(paramType).newInstance() : null);
|
||||
}
|
||||
|
||||
return constructor.newInstance(params.toArray());
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.core.mapping;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.expression.BeanFactoryAccessor;
|
||||
import org.springframework.context.expression.BeanFactoryResolver;
|
||||
import org.springframework.data.mapping.model.BasicPersistentEntity;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
|
||||
|
||||
public class BasicDocumentDbPersistentEntity<T> extends BasicPersistentEntity<T, DocumentDbPersistentProperty>
|
||||
implements DocumentDbPersistentEntity<T>, ApplicationContextAware {
|
||||
|
||||
private final StandardEvaluationContext context;
|
||||
|
||||
public BasicDocumentDbPersistentEntity(TypeInformation<T> typeInformation) {
|
||||
super(typeInformation);
|
||||
this.context = new StandardEvaluationContext();
|
||||
}
|
||||
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
context.addPropertyAccessor(new BeanFactoryAccessor());
|
||||
context.setBeanResolver(new BeanFactoryResolver(applicationContext));
|
||||
context.setRootObject(applicationContext);
|
||||
}
|
||||
|
||||
public String getCollection() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLanguage() {
|
||||
return "";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.core.mapping;
|
||||
|
||||
import org.springframework.data.mapping.Association;
|
||||
import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
|
||||
public class BasicDocumentDbPersistentProperty extends AnnotationBasedPersistentProperty<DocumentDbPersistentProperty>
|
||||
implements DocumentDbPersistentProperty {
|
||||
|
||||
private static final String ID_PROPERTY_NAME = "id";
|
||||
|
||||
public BasicDocumentDbPersistentProperty(Field field, PropertyDescriptor propertyDescriptor,
|
||||
DocumentDbPersistentEntity<?> owner,
|
||||
SimpleTypeHolder simpleTypeHolder) {
|
||||
super(field, propertyDescriptor, owner, simpleTypeHolder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Association<DocumentDbPersistentProperty> createAssociation() {
|
||||
return new Association<>(this, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIdProperty() {
|
||||
|
||||
if (super.isIdProperty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return getName().equals(ID_PROPERTY_NAME);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.core.mapping;
|
||||
|
||||
import org.springframework.data.annotation.Persistent;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Persistent
|
||||
@Inherited
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE})
|
||||
public @interface Document {
|
||||
|
||||
String collection() default "";
|
||||
|
||||
String ru() default "4000";
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.core.mapping;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.data.mapping.context.AbstractMappingContext;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
|
||||
public class DocumentDbMappingContext
|
||||
extends AbstractMappingContext<BasicDocumentDbPersistentEntity<?>, DocumentDbPersistentProperty>
|
||||
implements ApplicationContextAware {
|
||||
|
||||
private ApplicationContext context;
|
||||
|
||||
@Override
|
||||
protected <T> BasicDocumentDbPersistentEntity<T> createPersistentEntity(TypeInformation<T> typeInformation) {
|
||||
final BasicDocumentDbPersistentEntity<T> entity = new BasicDocumentDbPersistentEntity<>(typeInformation);
|
||||
|
||||
if (context != null) {
|
||||
entity.setApplicationContext(context);
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DocumentDbPersistentProperty createPersistentProperty(Field field, PropertyDescriptor propertyDescriptor,
|
||||
BasicDocumentDbPersistentEntity<?> owner,
|
||||
SimpleTypeHolder simpleTypeHolder) {
|
||||
return new BasicDocumentDbPersistentProperty(field, propertyDescriptor, owner,
|
||||
simpleTypeHolder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) {
|
||||
this.context = applicationContext;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.core.mapping;
|
||||
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
|
||||
|
||||
public interface DocumentDbPersistentEntity<T> extends PersistentEntity<T, DocumentDbPersistentProperty> {
|
||||
|
||||
String getCollection();
|
||||
|
||||
String getLanguage();
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.core.mapping;
|
||||
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
|
||||
|
||||
public interface DocumentDbPersistentProperty extends PersistentProperty<DocumentDbPersistentProperty> {
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.core.mapping;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Inherited
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.FIELD})
|
||||
public @interface PartitionKey {
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.repository;
|
||||
|
||||
import org.springframework.data.repository.NoRepositoryBean;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@NoRepositoryBean
|
||||
public interface DocumentDbRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID> {
|
||||
|
||||
@Override
|
||||
List<T> findAll();
|
||||
|
||||
void update(T entity);
|
||||
|
||||
List<T> findAll(String partitionKeyValue);
|
||||
|
||||
T findOne(ID id, String partitionKeyValue);
|
||||
|
||||
void delete(ID id, String partitionKeyValue);
|
||||
|
||||
void delete(T entity, String partitionKeyValue);
|
||||
|
||||
void update(T entity, String partitionKeyValue);
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.repository.config;
|
||||
|
||||
import org.springframework.data.repository.config.RepositoryBeanDefinitionRegistrarSupport;
|
||||
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
|
||||
public class DocumentDbRepositoriesRegistrar extends RepositoryBeanDefinitionRegistrarSupport {
|
||||
|
||||
@Override
|
||||
protected Class<? extends Annotation> getAnnotation() {
|
||||
return EnableDocumentDbRepositories.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RepositoryConfigurationExtension getExtension() {
|
||||
return new DocumentDbRepositoryConfigurationExtension();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.repository.config;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.core.mapping.DocumentDbMappingContext;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.repository.DocumentDbRepository;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.repository.support.DocumentDbRepositoryFactoryBean;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport;
|
||||
import org.springframework.data.repository.config.RepositoryConfigurationSource;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
|
||||
public class DocumentDbRepositoryConfigurationExtension extends RepositoryConfigurationExtensionSupport {
|
||||
|
||||
@Override
|
||||
public String getModuleName() {
|
||||
return "documentdb";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModulePrefix() {
|
||||
return "documentdb";
|
||||
}
|
||||
|
||||
public String getRepositoryFactoryBeanClassName() {
|
||||
return DocumentDbRepositoryFactoryBean.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRepositoryFactoryClassName() {
|
||||
return DocumentDbRepositoryFactoryBean.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<Class<?>> getIdentifyingTypes() {
|
||||
return Collections.<Class<?>>singleton(DocumentDbRepository.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<Class<? extends Annotation>> getIdentifyingAnnotations() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void registerBeansForRoot(BeanDefinitionRegistry registry, RepositoryConfigurationSource config) {
|
||||
super.registerBeansForRoot(registry, config);
|
||||
|
||||
final RootBeanDefinition definition = new RootBeanDefinition(DocumentDbMappingContext.class);
|
||||
definition.setRole(AbstractBeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
definition.setSource(config.getSource());
|
||||
|
||||
registry.registerBeanDefinition("documentDbMappingContext", definition);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.repository.config;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.repository.support.DocumentDbRepositoryFactoryBean;
|
||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.repository.config.DefaultRepositoryBaseClass;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Inherited
|
||||
@Import(DocumentDbRepositoriesRegistrar.class)
|
||||
public @interface EnableDocumentDbRepositories {
|
||||
|
||||
String[] value() default {};
|
||||
|
||||
String[] basePackages() default {};
|
||||
|
||||
Class<?>[] basePackageClasses() default {};
|
||||
|
||||
Filter[] includeFilters() default {};
|
||||
|
||||
Filter[] excludeFilters() default {};
|
||||
|
||||
String repositoryImplementationPostfix() default "Impl";
|
||||
|
||||
String namedQueriesLocation() default "";
|
||||
|
||||
QueryLookupStrategy.Key queryLookupStrategy() default QueryLookupStrategy.Key.CREATE_IF_NOT_FOUND;
|
||||
|
||||
Class<?> repositoryFactoryBeanClass() default DocumentDbRepositoryFactoryBean.class;
|
||||
|
||||
Class<?> repositoryBaseClass() default DefaultRepositoryBaseClass.class;
|
||||
|
||||
boolean considerNestedRepositories() default false;
|
||||
}
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.repository.support;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.core.mapping.Document;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.core.mapping.PartitionKey;
|
||||
import org.apache.commons.lang3.reflect.FieldUtils;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.repository.core.support.AbstractEntityInformation;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class DocumentDbEntityInformation<T, ID extends Serializable>
|
||||
extends AbstractEntityInformation<T, ID> {
|
||||
|
||||
private Field id;
|
||||
private Field partitionKeyField;
|
||||
private String collectionName;
|
||||
private Integer requestUnit;
|
||||
|
||||
public DocumentDbEntityInformation(Class<T> domainClass) {
|
||||
super(domainClass);
|
||||
|
||||
this.id = getIdField(domainClass);
|
||||
if (this.id != null) {
|
||||
ReflectionUtils.makeAccessible(this.id);
|
||||
}
|
||||
|
||||
this.collectionName = getCollectionName(domainClass);
|
||||
this.partitionKeyField = getPartitionKeyField(domainClass);
|
||||
if (this.partitionKeyField != null) {
|
||||
ReflectionUtils.makeAccessible(this.partitionKeyField);
|
||||
}
|
||||
|
||||
this.requestUnit = getRequestUnit(domainClass);
|
||||
}
|
||||
|
||||
|
||||
public ID getId(T entity) {
|
||||
return (ID) ReflectionUtils.getField(id, entity);
|
||||
}
|
||||
|
||||
public Class<ID> getIdType() {
|
||||
return (Class<ID>) id.getType();
|
||||
}
|
||||
|
||||
public String getCollectionName() {
|
||||
return this.collectionName;
|
||||
}
|
||||
|
||||
public Integer getRequestUint() {
|
||||
return this.requestUnit;
|
||||
}
|
||||
|
||||
public String getPartitionKeyFieldName() {
|
||||
return partitionKeyField == null ? null : partitionKeyField.getName();
|
||||
}
|
||||
|
||||
public String getPartitionKeyFieldValue(T entity) {
|
||||
return partitionKeyField == null ? null : (String) ReflectionUtils.getField(partitionKeyField, entity);
|
||||
}
|
||||
|
||||
private Field getIdField(Class<?> domainClass) {
|
||||
Field idField = null;
|
||||
|
||||
final List<Field> fields = FieldUtils.getFieldsListWithAnnotation(domainClass, Id.class);
|
||||
|
||||
if (fields.isEmpty()) {
|
||||
idField = ReflectionUtils.findField(getJavaType(), "id");
|
||||
} else if (fields.size() == 1) {
|
||||
idField = fields.get(0);
|
||||
} else {
|
||||
throw new IllegalArgumentException("only one field with @Id annotation!");
|
||||
}
|
||||
|
||||
if (idField != null && idField.getType() != String.class) {
|
||||
throw new IllegalArgumentException("type of id field must be String");
|
||||
}
|
||||
return idField;
|
||||
}
|
||||
|
||||
private String getCollectionName(Class<?> domainClass) {
|
||||
String customCollectionName = domainClass.getSimpleName();
|
||||
|
||||
final Document annotation = domainClass.getAnnotation(Document.class);
|
||||
|
||||
if (annotation != null && annotation.collection() != null && !annotation.collection().isEmpty()) {
|
||||
customCollectionName = annotation.collection();
|
||||
}
|
||||
|
||||
return customCollectionName;
|
||||
}
|
||||
|
||||
private Field getPartitionKeyField(Class<?> domainClass) {
|
||||
Field partitionKeyField = null;
|
||||
|
||||
final List<Field> fields = FieldUtils.getFieldsListWithAnnotation(domainClass, PartitionKey.class);
|
||||
|
||||
if (fields.size() == 1) {
|
||||
partitionKeyField = fields.get(0);
|
||||
} else if (fields.size() > 1) {
|
||||
throw new IllegalArgumentException("Azure Cosmos DB supports only one partition key, " +
|
||||
"only one field with @PartitionKey annotation!");
|
||||
}
|
||||
|
||||
if (partitionKeyField != null && partitionKeyField.getType() != String.class) {
|
||||
throw new IllegalArgumentException("type of PartitionKey field must be String");
|
||||
}
|
||||
return partitionKeyField;
|
||||
}
|
||||
|
||||
private Integer getRequestUnit(Class<?> domainClass) {
|
||||
Integer ru = 4000;
|
||||
final Document annotation = domainClass.getAnnotation(Document.class);
|
||||
|
||||
if (annotation != null && annotation.ru() != null && !annotation.ru().isEmpty()) {
|
||||
ru = Integer.parseInt(annotation.ru());
|
||||
}
|
||||
return ru;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.repository.support;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.data.repository.core.EntityInformation;
|
||||
import org.springframework.data.repository.core.RepositoryInformation;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
public class DocumentDbRepositoryFactory extends RepositoryFactorySupport {
|
||||
|
||||
private final ApplicationContext applicationContext;
|
||||
|
||||
public DocumentDbRepositoryFactory(ApplicationContext applicationContext) {
|
||||
this.applicationContext = applicationContext;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
|
||||
return SimpleDocumentDbRepository.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getTargetRepository(RepositoryInformation information) {
|
||||
final EntityInformation<?, Serializable> entityInformation = getEntityInformation(information.getDomainType());
|
||||
return getTargetRepositoryViaReflection(information, entityInformation, this.applicationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, ID extends Serializable> EntityInformation<T, ID> getEntityInformation(Class<T> domainClass) {
|
||||
return new DocumentDbEntityInformation<T, ID>(domainClass);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.repository.support;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.core.DocumentDbOperations;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport;
|
||||
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
public class DocumentDbRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable>
|
||||
extends RepositoryFactoryBeanSupport<T, S, ID>
|
||||
implements ApplicationContextAware {
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
private DocumentDbOperations operations;
|
||||
|
||||
|
||||
public DocumentDbRepositoryFactoryBean(Class<? extends T> repositoryInterface) {
|
||||
|
||||
super(repositoryInterface);
|
||||
}
|
||||
|
||||
public void setDocumentDbOperations(DocumentDbOperations operations) {
|
||||
this.operations = operations;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final RepositoryFactorySupport createRepositoryFactory() {
|
||||
return getFactoryInstance(applicationContext);
|
||||
}
|
||||
|
||||
protected RepositoryFactorySupport getFactoryInstance(ApplicationContext applicationContext) {
|
||||
return new DocumentDbRepositoryFactory(applicationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,270 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.repository.support;
|
||||
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.core.DocumentDbOperations;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.repository.DocumentDbRepository;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
public class SimpleDocumentDbRepository<T, ID extends Serializable> implements DocumentDbRepository<T, ID> {
|
||||
|
||||
private final DocumentDbOperations documentDbOperations;
|
||||
private final DocumentDbEntityInformation<T, ID> entityInformation;
|
||||
|
||||
public SimpleDocumentDbRepository(DocumentDbEntityInformation<T, ID> metadata,
|
||||
ApplicationContext applicationContext) {
|
||||
this.documentDbOperations = applicationContext.getBean(DocumentDbOperations.class);
|
||||
this.entityInformation = metadata;
|
||||
}
|
||||
|
||||
public SimpleDocumentDbRepository(DocumentDbEntityInformation<T, ID> metadata,
|
||||
DocumentDbOperations dbOperations) {
|
||||
this.documentDbOperations = dbOperations;
|
||||
this.entityInformation = metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* save entity without partition
|
||||
*
|
||||
* @param entity to be saved
|
||||
* @param <S>
|
||||
* @return entity
|
||||
*/
|
||||
@Override
|
||||
public <S extends T> S save(S entity) {
|
||||
Assert.notNull(entity, "entity must not be null");
|
||||
|
||||
// create collection if not exists
|
||||
documentDbOperations.createCollectionIfNotExists(entityInformation.getCollectionName(),
|
||||
entityInformation.getPartitionKeyFieldName(),
|
||||
entityInformation.getRequestUint());
|
||||
|
||||
// save entity
|
||||
documentDbOperations.insert(entityInformation.getCollectionName(),
|
||||
entity,
|
||||
entityInformation.getPartitionKeyFieldValue(entity));
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* batch save entities
|
||||
*
|
||||
* @param entities
|
||||
* @param <S>
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public <S extends T> Iterable<S> save(Iterable<S> entities) {
|
||||
throw new UnsupportedOperationException("save not supported yet.");
|
||||
}
|
||||
|
||||
/**
|
||||
* find all entities from one collection without partition
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<T> findAll() {
|
||||
return documentDbOperations.findAll(entityInformation.getCollectionName(),
|
||||
entityInformation.getJavaType(), null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* find entities based on id list from one collection without partitions
|
||||
*
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<T> findAll(Iterable<ID> ids) {
|
||||
throw new UnsupportedOperationException("findAll not supported yet.");
|
||||
}
|
||||
|
||||
/**
|
||||
* find one entity per id without partitions
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public T findOne(ID id) {
|
||||
Assert.notNull(id, "id must not be null");
|
||||
return documentDbOperations.findById(
|
||||
entityInformation.getCollectionName(), id, entityInformation.getJavaType(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<T> findAll(Pageable pageable) {
|
||||
throw new UnsupportedOperationException("findAll(Pageable pageable) not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<T> findAll(Sort sort) {
|
||||
throw new UnsupportedOperationException("findAll(Sort sort) Sort not supported yet.");
|
||||
}
|
||||
|
||||
/**
|
||||
* return count of documents in one collection without partitions
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public long count() {
|
||||
return findAll().size();
|
||||
}
|
||||
|
||||
/**
|
||||
* delete one document per id without partitions
|
||||
*
|
||||
* @param id
|
||||
*/
|
||||
@Override
|
||||
public void delete(ID id) {
|
||||
documentDbOperations.deleteById(entityInformation.getCollectionName(),
|
||||
id,
|
||||
entityInformation.getJavaType(),
|
||||
null);
|
||||
}
|
||||
|
||||
/**
|
||||
* delete one document per entity without partitions
|
||||
*
|
||||
* @param entity
|
||||
*/
|
||||
@Override
|
||||
public void delete(T entity) {
|
||||
documentDbOperations.deleteById(entityInformation.getCollectionName(),
|
||||
entityInformation.getId(entity),
|
||||
entityInformation.getJavaType(),
|
||||
null);
|
||||
}
|
||||
|
||||
/**
|
||||
* delete an collection
|
||||
*/
|
||||
@Override
|
||||
public void deleteAll() {
|
||||
documentDbOperations.deleteAll(entityInformation.getCollectionName());
|
||||
}
|
||||
|
||||
/**
|
||||
* delete list of entities without partitions
|
||||
*
|
||||
* @param entities
|
||||
*/
|
||||
@Override
|
||||
public void delete(Iterable<? extends T> entities) {
|
||||
throw new UnsupportedOperationException("delete not supported yet.");
|
||||
}
|
||||
|
||||
/**
|
||||
* check if an entity exists per id without partition
|
||||
*
|
||||
* @param primaryKey
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean exists(ID primaryKey) {
|
||||
return findOne(primaryKey) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* update an entity without partitions
|
||||
*
|
||||
* @param entity
|
||||
*/
|
||||
@Override
|
||||
public void update(T entity) {
|
||||
documentDbOperations.update(entityInformation.getCollectionName(),
|
||||
entity,
|
||||
((String) entityInformation.getId(entity)),
|
||||
null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* find all entities from one collection with partitions
|
||||
*
|
||||
* @param partitionKeyValue
|
||||
* @return
|
||||
*/
|
||||
public List<T> findAll(String partitionKeyValue) {
|
||||
return documentDbOperations.findAll(entityInformation.getCollectionName(),
|
||||
entityInformation.getJavaType(),
|
||||
entityInformation.getPartitionKeyFieldName(),
|
||||
partitionKeyValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* find one entity per id with partitions
|
||||
*
|
||||
* @param id
|
||||
* @param partitionKeyValue
|
||||
* @return
|
||||
*/
|
||||
public T findOne(ID id, String partitionKeyValue) {
|
||||
Assert.notNull(id, "id must not be null");
|
||||
Assert.notNull(partitionKeyValue, "partitionKeyValue must not be null");
|
||||
|
||||
return documentDbOperations.findById(
|
||||
entityInformation.getCollectionName(),
|
||||
id,
|
||||
entityInformation.getJavaType(),
|
||||
partitionKeyValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* delete an entity per id with partitions
|
||||
*
|
||||
* @param id
|
||||
* @param partitionKeyValue
|
||||
*/
|
||||
public void delete(ID id, String partitionKeyValue) {
|
||||
documentDbOperations.deleteById(entityInformation.getCollectionName(),
|
||||
id,
|
||||
entityInformation.getJavaType(),
|
||||
partitionKeyValue);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* delete an entity with partitions
|
||||
*
|
||||
* @param entity
|
||||
* @param partitionKeyValue
|
||||
*/
|
||||
public void delete(T entity, String partitionKeyValue) {
|
||||
documentDbOperations.deleteById(entityInformation.getCollectionName(),
|
||||
entityInformation.getId(entity),
|
||||
entityInformation.getJavaType(),
|
||||
partitionKeyValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* update an entity with partitions
|
||||
*
|
||||
* @param entity
|
||||
* @param partitionKeyValue
|
||||
*/
|
||||
public void update(T entity, String partitionKeyValue) {
|
||||
documentDbOperations.update(entityInformation.getCollectionName(),
|
||||
entity,
|
||||
((String) entityInformation.getId(entity)),
|
||||
partitionKeyValue);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
org.springframework.data.repository.core.support.RepositoryFactorySupport=com.microsoft.azure.spring.data.cosmosdb.documentdb.repository.support.DocumentDbRepositoryFactory
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class DocumentDbFactoryUnitTest {
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testNullKey() throws Exception {
|
||||
new DocumentDbFactory("https://fakeuri", null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidEndpoint() {
|
||||
final DocumentDbFactory factory = new DocumentDbFactory("https://fakeuri", "fakekey");
|
||||
assertThat(factory).isNotNull();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.config;
|
||||
|
||||
import com.microsoft.azure.documentdb.DocumentClient;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.DocumentDbFactory;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.support.AbstractApplicationContext;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
public class AbstractDocumentDbConfiguratinUnitTest {
|
||||
|
||||
@Rule
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void containsDocumentDbFactory() throws ClassNotFoundException {
|
||||
final AbstractApplicationContext context = new AnnotationConfigApplicationContext(
|
||||
TestDocumentDbConfiguration.class);
|
||||
|
||||
assertThat(context.getBean(DocumentDbFactory.class)).isNotNull();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class TestDocumentDbConfiguration extends AbstractDocumentDbConfiguration {
|
||||
@MockBean
|
||||
private DocumentClient mockClient;
|
||||
|
||||
@Override
|
||||
public String getDatabase() {
|
||||
return "testdb";
|
||||
}
|
||||
|
||||
@Override
|
||||
public DocumentClient documentClient() {
|
||||
return mockClient;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,209 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.core;
|
||||
|
||||
import com.microsoft.azure.documentdb.ConnectionPolicy;
|
||||
import com.microsoft.azure.documentdb.ConsistencyLevel;
|
||||
import com.microsoft.azure.documentdb.DocumentClient;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.core.convert.MappingDocumentDbConverter;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.core.mapping.DocumentDbMappingContext;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.domain.Person;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.domain.EntityScanner;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.data.annotation.Persistent;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@PropertySource(value = {"classpath:application.properties"})
|
||||
public class DocumentDbTemplateIT {
|
||||
|
||||
private static final String TEST_ID = "testid";
|
||||
private static final String TEST_NOTEXIST_ID = "testid2";
|
||||
|
||||
private static final String TEST_DB_NAME = "testdb";
|
||||
private static final Person TEST_PERSON = new Person(TEST_ID, "testfirstname", "testlastname");
|
||||
|
||||
private static final String PARTITION_KEY = "lastName";
|
||||
|
||||
@Value("${documentdb.uri}")
|
||||
private String documentDbUri;
|
||||
@Value("${documentdb.key}")
|
||||
private String documentDbKey;
|
||||
|
||||
private DocumentClient documentClient;
|
||||
private DocumentDbTemplate dbTemplate;
|
||||
|
||||
private MappingDocumentDbConverter dbConverter;
|
||||
private DocumentDbMappingContext mappingContext;
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
mappingContext = new DocumentDbMappingContext();
|
||||
try {
|
||||
mappingContext.setInitialEntitySet(new EntityScanner(this.applicationContext)
|
||||
.scan(Persistent.class));
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException(e.getMessage());
|
||||
|
||||
}
|
||||
dbConverter = new MappingDocumentDbConverter(mappingContext);
|
||||
documentClient = new DocumentClient(documentDbUri, documentDbKey,
|
||||
ConnectionPolicy.GetDefault(), ConsistencyLevel.Session);
|
||||
|
||||
dbTemplate = new DocumentDbTemplate(documentClient, dbConverter, TEST_DB_NAME);
|
||||
|
||||
dbTemplate.createCollectionIfNotExists(Person.class.getSimpleName(), null, null);
|
||||
dbTemplate.insert(Person.class.getSimpleName(), TEST_PERSON, null);
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanup() {
|
||||
dbTemplate.deleteAll(Person.class.getSimpleName());
|
||||
}
|
||||
|
||||
@Test(expected = RuntimeException.class)
|
||||
public void testInsertDuplicateId() throws Exception {
|
||||
dbTemplate.insert(Person.class.getSimpleName(), TEST_PERSON, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindAll() {
|
||||
final List<Person> result = dbTemplate.findAll(Person.class.getSimpleName(), Person.class, null, null);
|
||||
assertThat(result.size()).isEqualTo(1);
|
||||
assertThat(result.get(0).getId()).isEqualTo(TEST_PERSON.getId());
|
||||
assertThat(result.get(0).getFirstName()).isEqualTo(TEST_PERSON.getFirstName());
|
||||
assertThat(result.get(0).getLastName()).isEqualTo(TEST_PERSON.getLastName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindAllPartition() {
|
||||
setupPartition();
|
||||
|
||||
final List<Person> result = dbTemplate.findAll(Person.class.getSimpleName(),
|
||||
Person.class, PARTITION_KEY, TEST_PERSON.getLastName());
|
||||
|
||||
assertThat(result.size()).isEqualTo(1);
|
||||
assertThat(result.get(0).getId()).isEqualTo(TEST_PERSON.getId());
|
||||
assertThat(result.get(0).getFirstName()).isEqualTo(TEST_PERSON.getFirstName());
|
||||
assertThat(result.get(0).getLastName()).isEqualTo(TEST_PERSON.getLastName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindById() {
|
||||
final Person result = dbTemplate.findById(Person.class.getSimpleName(),
|
||||
TEST_PERSON.getId(), Person.class, null);
|
||||
assertThat(result.getId()).isEqualTo(TEST_PERSON.getId());
|
||||
assertThat(result.getFirstName()).isEqualTo(TEST_PERSON.getFirstName());
|
||||
assertThat(result.getLastName()).isEqualTo(TEST_PERSON.getLastName());
|
||||
|
||||
final Person nullResult = dbTemplate.findById(Person.class.getSimpleName(),
|
||||
TEST_NOTEXIST_ID, Person.class, null);
|
||||
assertThat(nullResult).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindByIdPartition() {
|
||||
setupPartition();
|
||||
|
||||
final Person result = dbTemplate.findById(Person.class.getSimpleName(),
|
||||
TEST_PERSON.getId(), Person.class, TEST_PERSON.getLastName());
|
||||
assertThat(result.getId()).isEqualTo(TEST_PERSON.getId());
|
||||
assertThat(result.getFirstName()).isEqualTo(TEST_PERSON.getFirstName());
|
||||
assertThat(result.getLastName()).isEqualTo(TEST_PERSON.getLastName());
|
||||
|
||||
final Person nullResult = dbTemplate.findById(Person.class.getSimpleName(),
|
||||
TEST_NOTEXIST_ID, Person.class, TEST_PERSON.getLastName());
|
||||
assertThat(nullResult).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdate() {
|
||||
final Person updated = new Person(TEST_PERSON.getId(), "updatedname",
|
||||
TEST_PERSON.getLastName());
|
||||
dbTemplate.update(Person.class.getSimpleName(), updated, updated.getId(), null);
|
||||
|
||||
final Person result = dbTemplate.findById(Person.class.getSimpleName(),
|
||||
updated.getId(), Person.class, null);
|
||||
|
||||
assertThat(result.getId()).isEqualTo(updated.getId());
|
||||
assertThat(result.getFirstName()).isEqualTo(updated.getFirstName());
|
||||
assertThat(result.getLastName()).isEqualTo(updated.getLastName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdatePartition() {
|
||||
setupPartition();
|
||||
final Person updated = new Person(TEST_PERSON.getId(), "updatedname",
|
||||
TEST_PERSON.getLastName());
|
||||
dbTemplate.update(Person.class.getSimpleName(), updated, updated.getId(), updated.getLastName());
|
||||
|
||||
final Person result = dbTemplate.findById(Person.class.getSimpleName(),
|
||||
updated.getId(), Person.class, updated.getLastName());
|
||||
|
||||
assertThat(result.getId()).isEqualTo(updated.getId());
|
||||
assertThat(result.getFirstName()).isEqualTo(updated.getFirstName());
|
||||
assertThat(result.getLastName()).isEqualTo(updated.getLastName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteById() {
|
||||
final Person person2 = new Person("newid", "newfn", "newln");
|
||||
dbTemplate.insert(person2, null);
|
||||
assertThat(dbTemplate.findAll(Person.class, null, null).size()).isEqualTo(2);
|
||||
|
||||
dbTemplate.deleteById(Person.class.getSimpleName(), TEST_PERSON.getId(), null, null);
|
||||
|
||||
final List<Person> result = dbTemplate.findAll(Person.class, null, null);
|
||||
assertThat(result.size()).isEqualTo(1);
|
||||
assertThat(result.get(0).getId()).isEqualTo(person2.getId());
|
||||
assertThat(result.get(0).getFirstName()).isEqualTo(person2.getFirstName());
|
||||
assertThat(result.get(0).getLastName()).isEqualTo(person2.getLastName());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteByIdPartition() {
|
||||
setupPartition();
|
||||
|
||||
// insert new document with same partition key
|
||||
final Person person2 = new Person("newid", "newfn", TEST_PERSON.getLastName());
|
||||
dbTemplate.insert(Person.class.getSimpleName(), person2, person2.getLastName());
|
||||
|
||||
assertThat(dbTemplate.findAll(Person.class, PARTITION_KEY, person2.getLastName()).size()).isEqualTo(2);
|
||||
|
||||
dbTemplate.deleteById(Person.class.getSimpleName(),
|
||||
TEST_PERSON.getId(), Person.class, TEST_PERSON.getLastName());
|
||||
|
||||
final List<Person> result = dbTemplate.findAll(Person.class, PARTITION_KEY, person2.getLastName());
|
||||
assertThat(result.size()).isEqualTo(1);
|
||||
assertThat(result.get(0).getId()).isEqualTo(person2.getId());
|
||||
assertThat(result.get(0).getFirstName()).isEqualTo(person2.getFirstName());
|
||||
assertThat(result.get(0).getLastName()).isEqualTo(person2.getLastName());
|
||||
|
||||
}
|
||||
|
||||
private void setupPartition() {
|
||||
cleanup();
|
||||
|
||||
dbTemplate.createCollectionIfNotExists(Person.class.getSimpleName(), PARTITION_KEY, 1000);
|
||||
dbTemplate.insert(Person.class.getSimpleName(), TEST_PERSON, TEST_PERSON.getLastName());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.core;
|
||||
|
||||
import com.microsoft.azure.documentdb.DocumentClient;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.DocumentDbFactory;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.core.convert.MappingDocumentDbConverter;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DocumentDbTemplateUnitTest {
|
||||
|
||||
DocumentDbTemplate dbTemplate;
|
||||
|
||||
@Mock
|
||||
DocumentClient documentClient;
|
||||
|
||||
@Mock
|
||||
MappingDocumentDbConverter dbConverter;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.dbTemplate = new DocumentDbTemplate(new DocumentDbFactory(documentClient), dbConverter, "testdb");
|
||||
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectNullDbFactory() throws Exception {
|
||||
new DocumentDbTemplate(documentClient, null, "testdb");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.core.converter;
|
||||
|
||||
|
||||
import com.microsoft.azure.documentdb.Document;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.core.convert.DocumentDbConverter;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.domain.Person;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class DocumentDbConverterUnitTest {
|
||||
|
||||
private static final String id = "testId";
|
||||
private static final String firstName = "testFirstName";
|
||||
private static final String lastName = "testLastName";
|
||||
private static final String idPropertyName = "id";
|
||||
private static final String firstNamePropertyName = "firstName";
|
||||
private static final String lastNamePropertyName = "lastName";
|
||||
private DocumentDbConverter dbConverter;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
dbConverter = new DocumentDbConverter();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertFromEntityToDocument() {
|
||||
final Person person = new Person(id, firstName, lastName);
|
||||
final Document document = dbConverter.convertToDocument(person);
|
||||
|
||||
assertThat(document.has(idPropertyName)).isTrue();
|
||||
assertThat(document.has(firstNamePropertyName)).isTrue();
|
||||
assertThat(document.has(lastNamePropertyName)).isTrue();
|
||||
assertThat(document.getId()).isEqualTo(id);
|
||||
assertThat(document.getString(firstNamePropertyName)).isEqualTo(firstName);
|
||||
assertThat(document.getString(lastNamePropertyName)).isEqualTo(lastName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertFromDocumentToEntity() {
|
||||
final JSONObject json = new JSONObject();
|
||||
json.put(idPropertyName, id);
|
||||
json.put(firstNamePropertyName, firstName);
|
||||
json.put(lastNamePropertyName, lastName);
|
||||
|
||||
final Document document = new Document(JSONObject.valueToString(json));
|
||||
final Person person = dbConverter.convertFromDocument(document, Person.class);
|
||||
assertThat(person.getId()).isEqualTo(id);
|
||||
assertThat(person.getFirstName()).isEqualTo(firstName);
|
||||
assertThat(person.getLastName()).isEqualTo(lastName);
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.core.converter;
|
||||
|
||||
import com.microsoft.azure.documentdb.Document;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.core.convert.MappingDocumentDbConverter;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.core.mapping.DocumentDbMappingContext;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.domain.Address;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class MappingDocumentDbConverterUnitTest {
|
||||
|
||||
MappingDocumentDbConverter dbConverter;
|
||||
|
||||
DocumentDbMappingContext mappingContext;
|
||||
|
||||
@Mock
|
||||
ApplicationContext applicationContext;
|
||||
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
mappingContext = new DocumentDbMappingContext();
|
||||
mappingContext.setApplicationContext(applicationContext);
|
||||
mappingContext.afterPropertiesSet();
|
||||
|
||||
mappingContext.getPersistentEntity(Address.class);
|
||||
|
||||
dbConverter = new MappingDocumentDbConverter(mappingContext);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void covertAddressToDocumentCorrectly() {
|
||||
final Address testAddress = new Address("98052", "testCity", "testStreet");
|
||||
|
||||
final Document document = new Document();
|
||||
|
||||
dbConverter.write(testAddress, document);
|
||||
|
||||
assertThat(document.getId()).isEqualTo(testAddress.getPostalCode());
|
||||
assertThat(document.getString("city")).isEqualTo(testAddress.getCity());
|
||||
assertThat(document.getString("street")).isEqualTo(testAddress.getStreet());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertDocumentToAddressCorrectly() {
|
||||
final Document document = new Document();
|
||||
|
||||
document.setId("testId");
|
||||
document.set("city", "testCity");
|
||||
document.set("street", "testStreet");
|
||||
|
||||
final Address address = dbConverter.read(Address.class, document);
|
||||
|
||||
assertThat(address.getPostalCode()).isEqualTo("testId");
|
||||
assertThat(address.getCity()).isEqualTo("testCity");
|
||||
assertThat(address.getStreet()).isEqualTo("testStreet");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.core.mapping;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.domain.Person;
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class BasicDocumentDbPersistentEntityUnitTest {
|
||||
|
||||
@Test
|
||||
public void testGetCollection() {
|
||||
final BasicDocumentDbPersistentEntity entity = new BasicDocumentDbPersistentEntity<Person>(
|
||||
ClassTypeInformation.from(Person.class));
|
||||
assertThat(entity.getCollection()).isEqualTo("");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetLanguage() {
|
||||
final BasicDocumentDbPersistentEntity entity = new BasicDocumentDbPersistentEntity<Person>(
|
||||
ClassTypeInformation.from(Person.class));
|
||||
assertThat(entity.getLanguage()).isEqualTo("");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.core.mapping;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DocumentDbMappingContextUnitTest {
|
||||
|
||||
@Mock
|
||||
ApplicationContext context;
|
||||
|
||||
@Test
|
||||
public void mappingContextWithImplicitIdProperty() {
|
||||
final DocumentDbMappingContext context = new DocumentDbMappingContext();
|
||||
final BasicDocumentDbPersistentEntity<?> entity = context.getPersistentEntity(ClassWithId.class);
|
||||
|
||||
assertThat(entity).isNotNull();
|
||||
}
|
||||
|
||||
class ClassWithId {
|
||||
String field;
|
||||
String id;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.domain;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.core.mapping.Document;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.core.mapping.PartitionKey;
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
@Document(ru = "1000")
|
||||
public class Address {
|
||||
@Id
|
||||
String postalCode;
|
||||
String street;
|
||||
@PartitionKey
|
||||
String city;
|
||||
|
||||
public Address(String postalCode, String city, String street) {
|
||||
this.postalCode = postalCode;
|
||||
this.city = city;
|
||||
this.street = street;
|
||||
}
|
||||
|
||||
public String getCity() {
|
||||
return city;
|
||||
}
|
||||
|
||||
public void setCity(String city) {
|
||||
this.city = city;
|
||||
}
|
||||
|
||||
public String getStreet() {
|
||||
return street;
|
||||
}
|
||||
|
||||
public void setStreet(String street) {
|
||||
this.street = street;
|
||||
}
|
||||
|
||||
public String getPostalCode() {
|
||||
return this.postalCode;
|
||||
}
|
||||
|
||||
public void setPostalCode(String code) {
|
||||
this.postalCode = code;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.domain;
|
||||
|
||||
|
||||
public class Person {
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
|
||||
private String id;
|
||||
|
||||
public Person() {
|
||||
this(null, null, null);
|
||||
}
|
||||
|
||||
public Person(String id, String fname, String lname) {
|
||||
this.firstName = fname;
|
||||
this.lastName = lname;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
||||
public void setFirstName(String fname) {
|
||||
this.firstName = fname;
|
||||
}
|
||||
|
||||
public String getLastName() {
|
||||
return lastName;
|
||||
}
|
||||
|
||||
public void setLastName(String lastName) {
|
||||
this.lastName = lastName;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.domain;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.repository.DocumentDbRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface PersonRepository extends DocumentDbRepository<Person, String> {
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.repository;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.domain.Address;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface AddressRepository extends DocumentDbRepository<Address, String> {
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.repository;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.domain.Address;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(classes = ContactRepositoryConfig.class)
|
||||
public class AddressRepositoryIT {
|
||||
|
||||
private static final Address TEST_ADDRESS1_PARTITION1 = new Address("111", "redmond", "111st avenue");
|
||||
private static final Address TEST_ADDRESS2_PARTITION1 = new Address("222", "redmond", "98th street");
|
||||
private static final Address TEST_ADDRESS1_PARTITION2 = new Address("333", "bellevue", "103rd street");
|
||||
|
||||
@Autowired
|
||||
AddressRepository repository;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
repository.save(TEST_ADDRESS1_PARTITION1);
|
||||
repository.save(TEST_ADDRESS1_PARTITION2);
|
||||
repository.save(TEST_ADDRESS2_PARTITION1);
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanup() {
|
||||
repository.deleteAll();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindAll() {
|
||||
// findAll cross partition
|
||||
final List<Address> result = repository.findAll();
|
||||
|
||||
assertThat(result.size()).isEqualTo(3);
|
||||
|
||||
// findAll per partition
|
||||
final List<Address> partition1 = repository.findAll(TEST_ADDRESS1_PARTITION1.getCity());
|
||||
assertThat(partition1.size()).isEqualTo(2);
|
||||
|
||||
final List<Address> partition2 = repository.findAll(TEST_ADDRESS1_PARTITION2.getCity());
|
||||
assertThat(partition2.size()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCountAndDeleteByID() {
|
||||
long count = repository.count();
|
||||
assertThat(count).isEqualTo(3);
|
||||
|
||||
repository.delete(TEST_ADDRESS1_PARTITION1.getPostalCode(), TEST_ADDRESS1_PARTITION1.getCity());
|
||||
|
||||
final List<Address> result = repository.findAll();
|
||||
|
||||
assertThat(result.size()).isEqualTo(2);
|
||||
|
||||
count = repository.count();
|
||||
assertThat(count).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCountAndDeleteEntity() {
|
||||
repository.delete(TEST_ADDRESS1_PARTITION1, TEST_ADDRESS1_PARTITION1.getCity());
|
||||
|
||||
final List<Address> result = repository.findAll();
|
||||
|
||||
assertThat(result.size()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateEntity() {
|
||||
final Address updatedAddress = new Address(TEST_ADDRESS1_PARTITION1.getPostalCode(),
|
||||
TEST_ADDRESS1_PARTITION1.getCity(), "new street");
|
||||
|
||||
repository.update(updatedAddress, updatedAddress.getCity());
|
||||
|
||||
final Address address = repository.findOne(updatedAddress.getPostalCode(), updatedAddress.getCity());
|
||||
|
||||
assertThat(address.getStreet()).isEqualTo(updatedAddress.getStreet());
|
||||
assertThat(address.getPostalCode()).isEqualTo(updatedAddress.getPostalCode());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.repository;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
public class Contact {
|
||||
@Id
|
||||
private String logicId;
|
||||
|
||||
private String title;
|
||||
|
||||
public Contact(String id, String title) {
|
||||
this.logicId = id;
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getLogicId() {
|
||||
return logicId;
|
||||
}
|
||||
|
||||
public void setLogicId(String logicId) {
|
||||
this.logicId = logicId;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.repository;
|
||||
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface ContactRepository extends DocumentDbRepository<Contact, String> {
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.repository;
|
||||
|
||||
import com.microsoft.azure.documentdb.ConnectionPolicy;
|
||||
import com.microsoft.azure.documentdb.ConsistencyLevel;
|
||||
import com.microsoft.azure.documentdb.DocumentClient;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.config.AbstractDocumentDbConfiguration;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.repository.config.EnableDocumentDbRepositories;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
|
||||
@Configuration
|
||||
@PropertySource(value = {"classpath:application.properties"})
|
||||
@EnableDocumentDbRepositories
|
||||
public class ContactRepositoryConfig extends AbstractDocumentDbConfiguration {
|
||||
@Value("${documentdb.uri}")
|
||||
String dbUri;
|
||||
|
||||
@Value("${documentdb.key}")
|
||||
String dbKey;
|
||||
|
||||
@Override
|
||||
public DocumentClient documentClient() {
|
||||
return new DocumentClient(dbUri, dbKey, ConnectionPolicy.GetDefault(), ConsistencyLevel.Session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDatabase() {
|
||||
return "itdb";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.repository;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(classes = ContactRepositoryConfig.class)
|
||||
public class ContactRepositoryIT {
|
||||
|
||||
private static final Contact TEST_CONTACT = new Contact("testId", "faketitle");
|
||||
|
||||
@Autowired
|
||||
ContactRepository repository;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
repository.save(TEST_CONTACT);
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanup() {
|
||||
repository.deleteAll();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindAll() {
|
||||
final List<Contact> result = repository.findAll();
|
||||
|
||||
assertThat(result.size()).isEqualTo(1);
|
||||
assertThat(result.get(0).getLogicId()).isEqualTo(TEST_CONTACT.getLogicId());
|
||||
assertThat(result.get(0).getTitle()).isEqualTo(TEST_CONTACT.getTitle());
|
||||
|
||||
final Contact contact = repository.findOne(TEST_CONTACT.getLogicId());
|
||||
|
||||
assertThat(contact.getLogicId()).isEqualTo(TEST_CONTACT.getLogicId());
|
||||
assertThat(contact.getTitle()).isEqualTo(TEST_CONTACT.getTitle());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCountAndDeleteByID() {
|
||||
final Contact contact2 = new Contact("newid", "newtitle");
|
||||
repository.save(contact2);
|
||||
final List<Contact> all = repository.findAll();
|
||||
assertThat(all.size()).isEqualTo(2);
|
||||
|
||||
long count = repository.count();
|
||||
assertThat(count).isEqualTo(2);
|
||||
|
||||
repository.delete(contact2.getLogicId());
|
||||
|
||||
final List<Contact> result = repository.findAll();
|
||||
|
||||
assertThat(result.size()).isEqualTo(1);
|
||||
assertThat(result.get(0).getLogicId()).isEqualTo(TEST_CONTACT.getLogicId());
|
||||
assertThat(result.get(0).getTitle()).isEqualTo(TEST_CONTACT.getTitle());
|
||||
|
||||
count = repository.count();
|
||||
assertThat(count).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCountAndDeleteEntity() {
|
||||
final Contact contact2 = new Contact("newid", "newtitle");
|
||||
repository.save(contact2);
|
||||
final List<Contact> all = repository.findAll();
|
||||
assertThat(all.size()).isEqualTo(2);
|
||||
|
||||
repository.delete(contact2);
|
||||
|
||||
final List<Contact> result = repository.findAll();
|
||||
|
||||
assertThat(result.size()).isEqualTo(1);
|
||||
assertThat(result.get(0).getLogicId()).isEqualTo(TEST_CONTACT.getLogicId());
|
||||
assertThat(result.get(0).getTitle()).isEqualTo(TEST_CONTACT.getTitle());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateEntity() {
|
||||
final Contact updatedContact = new Contact(TEST_CONTACT.getLogicId(), "updated");
|
||||
|
||||
repository.update(updatedContact);
|
||||
|
||||
final Contact contact = repository.findOne(TEST_CONTACT.getLogicId());
|
||||
|
||||
assertThat(contact.getLogicId()).isEqualTo(updatedContact.getLogicId());
|
||||
assertThat(contact.getTitle()).isEqualTo(updatedContact.getTitle());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.repository;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.core.DocumentDbOperations;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.domain.Person;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.repository.support.DocumentDbEntityInformation;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.repository.support.SimpleDocumentDbRepository;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class SimpleDocumentDbRepositoryUnitTest {
|
||||
|
||||
private static final Person TEST_PERSON = new Person("aaa", "firstname", "lastname");
|
||||
SimpleDocumentDbRepository<Person, String> repository;
|
||||
@Mock
|
||||
DocumentDbOperations dbOperations;
|
||||
@Mock
|
||||
DocumentDbEntityInformation<Person, String> entityInformation;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
when(entityInformation.getJavaType()).thenReturn(Person.class);
|
||||
when(entityInformation.getCollectionName()).thenReturn(Person.class.getSimpleName());
|
||||
when(entityInformation.getPartitionKeyFieldName()).thenReturn("lastName");
|
||||
when(entityInformation.getRequestUint()).thenReturn(1000);
|
||||
when(dbOperations.findAll(anyString(), any(), anyString(), anyString()))
|
||||
.thenReturn(Arrays.asList(TEST_PERSON));
|
||||
|
||||
repository = new SimpleDocumentDbRepository<Person, String>(entityInformation, dbOperations);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSave() {
|
||||
repository.save(TEST_PERSON);
|
||||
|
||||
assertEquals(1, repository.findAll(TEST_PERSON.getLastName()).size());
|
||||
assertEquals(TEST_PERSON.getFirstName(), repository.findAll(TEST_PERSON.getLastName()).get(0).getFirstName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOne() {
|
||||
when(dbOperations.findById(anyString(), any(), any(), anyString())).thenReturn(TEST_PERSON);
|
||||
|
||||
repository.save(TEST_PERSON);
|
||||
|
||||
final Person result = repository.findOne(TEST_PERSON.getId(), TEST_PERSON.getLastName());
|
||||
|
||||
assertEquals(result.getId(), TEST_PERSON.getId());
|
||||
assertEquals(result.getFirstName(), TEST_PERSON.getFirstName());
|
||||
assertEquals(result.getLastName(), TEST_PERSON.getLastName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdate() {
|
||||
final Person updatedPerson = new Person(TEST_PERSON.getId(), "updated", "updated");
|
||||
repository.update(updatedPerson);
|
||||
|
||||
when(dbOperations.findById(anyString(), any(), any(), anyString())).thenReturn(updatedPerson);
|
||||
|
||||
final Person result = repository.findOne(TEST_PERSON.getId(), TEST_PERSON.getLastName());
|
||||
|
||||
assertEquals(result.getId(), updatedPerson.getId());
|
||||
assertEquals(result.getFirstName(), updatedPerson.getFirstName());
|
||||
assertEquals(result.getLastName(), updatedPerson.getLastName());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.repository.config;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.repository.DocumentDbRepository;
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
import org.springframework.core.type.StandardAnnotationMetadata;
|
||||
import org.springframework.data.repository.config.AnnotationRepositoryConfigurationSource;
|
||||
import org.springframework.data.repository.config.RepositoryConfiguration;
|
||||
import org.springframework.data.repository.config.RepositoryConfigurationSource;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import static org.assertj.core.api.Assertions.fail;
|
||||
|
||||
public class DocumentDbRepositoryConfigurationExtensionUnitTest {
|
||||
|
||||
StandardAnnotationMetadata metadata = new StandardAnnotationMetadata(Config.class, true);
|
||||
ResourceLoader loader = new PathMatchingResourcePatternResolver();
|
||||
Environment environment = new StandardEnvironment();
|
||||
RepositoryConfigurationSource configurationSource = new AnnotationRepositoryConfigurationSource(metadata,
|
||||
EnableDocumentDbRepositories.class, loader, environment);
|
||||
|
||||
private static void assertHashRepo(Class<?> repositoryInterface,
|
||||
Collection<RepositoryConfiguration<RepositoryConfigurationSource>> configs) {
|
||||
for (final RepositoryConfiguration<?> config : configs) {
|
||||
if (config.getRepositoryInterface().equals(repositoryInterface.getName())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fail("expected to find config for repository interface "
|
||||
+ repositoryInterface.getName() + ", but got: " + configs.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isStrictMatchIfRepositoryExtendsStoreSpecificBase() {
|
||||
final DocumentDbRepositoryConfigurationExtension extension = new DocumentDbRepositoryConfigurationExtension();
|
||||
assertHashRepo(TestRepository.class, extension.getRepositoryConfigurations(configurationSource, loader, true));
|
||||
}
|
||||
|
||||
interface TestRepository extends DocumentDbRepository<Object, String> {
|
||||
}
|
||||
|
||||
@EnableDocumentDbRepositories(considerNestedRepositories = true)
|
||||
static class Config {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.repository.support;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.core.mapping.Document;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.domain.Person;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class DocumentDbEntityInformationUnitTest {
|
||||
|
||||
@Test
|
||||
public void testGetId() {
|
||||
final Person testPerson = new Person("test", "test", "test");
|
||||
final DocumentDbEntityInformation<Person, String> entityInformation =
|
||||
new DocumentDbEntityInformation<Person, String>(Person.class);
|
||||
|
||||
final String idField = entityInformation.getId(testPerson);
|
||||
|
||||
assertThat(idField).isEqualTo(testPerson.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetIdType() {
|
||||
final DocumentDbEntityInformation<Person, String> entityInformation =
|
||||
new DocumentDbEntityInformation<Person, String>(Person.class);
|
||||
|
||||
final Class<?> idType = entityInformation.getIdType();
|
||||
assertThat(idType.getSimpleName()).isEqualTo(String.class.getSimpleName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCollectionName() {
|
||||
final DocumentDbEntityInformation<Person, String> entityInformation =
|
||||
new DocumentDbEntityInformation<Person, String>(Person.class);
|
||||
|
||||
final String collectionName = entityInformation.getCollectionName();
|
||||
assertThat(collectionName).isEqualTo(Person.class.getSimpleName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomCollectionName() {
|
||||
final DocumentDbEntityInformation<Volunteer, String> entityInformation =
|
||||
new DocumentDbEntityInformation<Volunteer, String>(Volunteer.class);
|
||||
|
||||
final String collectionName = entityInformation.getCollectionName();
|
||||
assertThat(collectionName).isEqualTo("testCollection");
|
||||
}
|
||||
|
||||
@Document(collection = "testCollection")
|
||||
class Volunteer {
|
||||
String id;
|
||||
String name;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.repository.support;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.domain.PersonRepository;
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class DocumentDbRepositoryFactoryBeanUnitTest {
|
||||
@Test
|
||||
public void testCreateRepositoryFactory() {
|
||||
final DocumentDbRepositoryFactoryBean factoryBean = new DocumentDbRepositoryFactoryBean(PersonRepository.class);
|
||||
final RepositoryFactorySupport factory = factoryBean.createRepositoryFactory();
|
||||
assertThat(factory).isNotNull();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.documentdb.repository.support;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.core.mapping.DocumentDbPersistentEntity;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.documentdb.domain.Person;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.repository.core.EntityInformation;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DocumentDbRepositoryFactoryUnitTest {
|
||||
|
||||
@Mock
|
||||
MappingContext mappingContext;
|
||||
|
||||
@Mock
|
||||
DocumentDbPersistentEntity entity;
|
||||
|
||||
@Autowired
|
||||
ApplicationContext applicationContext;
|
||||
|
||||
@Test
|
||||
public void useMappingDocumentDBEntityInfoIfMappingContextSet() {
|
||||
final DocumentDbRepositoryFactory factory = new DocumentDbRepositoryFactory(applicationContext);
|
||||
final EntityInformation<Person, String> entityInfo = factory.getEntityInformation(Person.class);
|
||||
assertTrue(entityInfo instanceof DocumentDbEntityInformation);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
#Mon, 07 Aug 2017 11:09:48 +0800
|
||||
#test properties for documentdb emulator, from https://docs.microsoft.com/en-us/azure/cosmos-db/local-emulator
|
||||
documentdb.key=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==
|
||||
documentdb.uri=${DOCUMENTDB_URI}
|
Загрузка…
Ссылка в новой задаче