docs) -> {
+ logger.info("--->setHandleChanges() START");
+
+ for (JsonNode document : docs) {
+ try {
+ //Change Feed hands the document to you in the form of a JsonNode
+ //As a developer you have two options for handling the JsonNode document provided to you by Change Feed
+ //One option is to operate on the document in the form of a JsonNode, as shown below. This is great
+ //especially if you do not have a single uniform data model for all documents.
+ logger.info("---->DOCUMENT RECEIVED: " + OBJECT_MAPPER.writerWithDefaultPrettyPrinter()
+ .writeValueAsString(document));
+
+ //You can also transform the JsonNode to a POJO having the same structure as the JsonNode,
+ //as shown below. Then you can operate on the POJO.
+ CustomPOJO pojo_doc = OBJECT_MAPPER.treeToValue(document, CustomPOJO.class);
+ logger.info("----=>id: " + pojo_doc.getId());
+
+ } catch (JsonProcessingException e) {
+ e.printStackTrace();
+ }
+ }
+ logger.info("--->handleChanges() END");
+
+ })
+ .build();
+ }
+
+ public static CosmosAsyncClient getCosmosClient() {
+
+ return new CosmosClientBuilder()
+ .setEndpoint(SampleConfigurations.HOST)
+ .setKey(SampleConfigurations.MASTER_KEY)
+ .setConnectionPolicy(ConnectionPolicy.getDefaultPolicy())
+ .setConsistencyLevel(ConsistencyLevel.EVENTUAL)
+ .buildAsyncClient();
+ }
+
+ public static CosmosAsyncDatabase createNewDatabase(CosmosAsyncClient client, String databaseName) {
+ return client.createDatabaseIfNotExists(databaseName).block().getDatabase();
+ }
+
+ public static void deleteDatabase(CosmosAsyncDatabase cosmosDatabase) {
+ cosmosDatabase.delete().block();
+ }
+
+ public static CosmosAsyncContainer createNewCollection(CosmosAsyncClient client, String databaseName, String collectionName) {
+ CosmosAsyncDatabase databaseLink = client.getDatabase(databaseName);
+ CosmosAsyncContainer collectionLink = databaseLink.getContainer(collectionName);
+ CosmosAsyncContainerResponse containerResponse = null;
+
+ try {
+ containerResponse = collectionLink.read().block();
+
+ if (containerResponse != null) {
+ throw new IllegalArgumentException(String.format("Collection %s already exists in database %s.", collectionName, databaseName));
+ }
+ } catch (RuntimeException ex) {
+ if (ex instanceof CosmosClientException) {
+ CosmosClientException cosmosClientException = (CosmosClientException) ex;
+
+ if (cosmosClientException.getStatusCode() != 404) {
+ throw ex;
+ }
+ } else {
+ throw ex;
+ }
+ }
+
+ CosmosContainerProperties containerSettings = new CosmosContainerProperties(collectionName, "/id");
+ CosmosContainerRequestOptions requestOptions = new CosmosContainerRequestOptions();
+ containerResponse = databaseLink.createContainer(containerSettings, 10000, requestOptions).block();
+
+ if (containerResponse == null) {
+ throw new RuntimeException(String.format("Failed to create collection %s in database %s.", collectionName, databaseName));
+ }
+
+ return containerResponse.getContainer();
+ }
+
+ public static CosmosAsyncContainer createNewLeaseCollection(CosmosAsyncClient client, String databaseName, String leaseCollectionName) {
+ CosmosAsyncDatabase databaseLink = client.getDatabase(databaseName);
+ CosmosAsyncContainer leaseCollectionLink = databaseLink.getContainer(leaseCollectionName);
+ CosmosAsyncContainerResponse leaseContainerResponse = null;
+
+ try {
+ leaseContainerResponse = leaseCollectionLink.read().block();
+
+ if (leaseContainerResponse != null) {
+ leaseCollectionLink.delete().block();
+
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException ex) {
+ ex.printStackTrace();
+ }
+ }
+ } catch (RuntimeException ex) {
+ if (ex instanceof CosmosClientException) {
+ CosmosClientException cosmosClientException = (CosmosClientException) ex;
+
+ if (cosmosClientException.getStatusCode() != 404) {
+ throw ex;
+ }
+ } else {
+ throw ex;
+ }
+ }
+
+ CosmosContainerProperties containerSettings = new CosmosContainerProperties(leaseCollectionName, "/id");
+ CosmosContainerRequestOptions requestOptions = new CosmosContainerRequestOptions();
+
+ leaseContainerResponse = databaseLink.createContainer(containerSettings, 400, requestOptions).block();
+
+ if (leaseContainerResponse == null) {
+ throw new RuntimeException(String.format("Failed to create collection %s in database %s.", leaseCollectionName, databaseName));
+ }
+
+ return leaseContainerResponse.getContainer();
+ }
+
+ public static void createNewDocumentsCustomPOJO(CosmosAsyncContainer containerClient, int count, Duration delay) {
+ String suffix = RandomStringUtils.randomAlphabetic(10);
+ for (int i = 0; i <= count; i++) {
+ CustomPOJO document = new CustomPOJO();
+ document.setId(String.format("0%d-%s", i, suffix));
+
+ containerClient.createItem(document).subscribe(doc -> {
+ logger.info("---->DOCUMENT WRITE: " + doc);
+ });
+
+ long remainingWork = delay.toMillis();
+ try {
+ while (remainingWork > 0) {
+ Thread.sleep(100);
+ remainingWork -= 100;
+ }
+ } catch (InterruptedException iex) {
+ // exception caught
+ break;
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/azure/cosmos/examples/changefeed/SampleConfigurations.java b/src/main/java/com/azure/cosmos/examples/changefeed/SampleConfigurations.java
new file mode 100644
index 0000000..f373f7e
--- /dev/null
+++ b/src/main/java/com/azure/cosmos/examples/changefeed/SampleConfigurations.java
@@ -0,0 +1,36 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.cosmos.examples.changefeed;
+
+import com.google.common.base.Strings;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * Contains the configurations for tests.
+ *
+ * For running tests, you can pass a customized endpoint configuration in one of the following
+ * ways:
+ *
+ * - -DACCOUNT_KEY="[your-key]" -ACCOUNT_HOST="[your-endpoint]" as JVM
+ * command-line option.
+ * - You can set ACCOUNT_KEY and ACCOUNT_HOST as environment variables.
+ *
+ *
+ * If none of the above is set, emulator endpoint will be used.
+ */
+public final class SampleConfigurations {
+ // REPLACE MASTER_KEY and HOST with values from your Azure Cosmos DB account.
+ // The default values are credentials of the local emulator, which are not used in any production environment.
+ //
+ public static String MASTER_KEY =
+ System.getProperty("ACCOUNT_KEY",
+ StringUtils.defaultString(Strings.emptyToNull(
+ System.getenv().get("ACCOUNT_KEY")),
+ "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="));
+
+ public static String HOST =
+ System.getProperty("ACCOUNT_HOST",
+ StringUtils.defaultString(Strings.emptyToNull(
+ System.getenv().get("ACCOUNT_HOST")),
+ "https://localhost:8081/"));
+}
diff --git a/src/main/java/com/azure/cosmos/examples/common/AccountSettings.java b/src/main/java/com/azure/cosmos/examples/common/AccountSettings.java
new file mode 100644
index 0000000..64a7776
--- /dev/null
+++ b/src/main/java/com/azure/cosmos/examples/common/AccountSettings.java
@@ -0,0 +1,40 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.cosmos.examples.common;
+
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * Contains the account configurations for Sample.
+ *
+ * For running tests, you can pass a customized endpoint configuration in one of the following
+ * ways:
+ *
+ * - -DACCOUNT_KEY="[your-key]" -ACCOUNT_HOST="[your-endpoint]" as JVM
+ * command-line option.
+ * - You can set ACCOUNT_KEY and ACCOUNT_HOST as environment variables.
+ *
+ *
+ * If none of the above is set, emulator endpoint will be used.
+ * Emulator http cert is self signed. If you are using emulator,
+ * make sure emulator https certificate is imported
+ * to java trusted cert store:
+ * https://docs.microsoft.com/en-us/azure/cosmos-db/local-emulator-export-ssl-certificates
+ */
+public class AccountSettings {
+ // Replace MASTER_KEY and HOST with values from your Azure Cosmos DB account.
+ // The default values are credentials of the local emulator, which are not used in any production environment.
+ //
+ public static String MASTER_KEY =
+ System.getProperty("ACCOUNT_KEY",
+ StringUtils.defaultString(StringUtils.trimToNull(
+ System.getenv().get("ACCOUNT_KEY")),
+ "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="));
+
+ public static String HOST =
+ System.getProperty("ACCOUNT_HOST",
+ StringUtils.defaultString(StringUtils.trimToNull(
+ System.getenv().get("ACCOUNT_HOST")),
+ "https://localhost:443/"));
+}
diff --git a/src/main/java/com/azure/cosmos/examples/common/Address.java b/src/main/java/com/azure/cosmos/examples/common/Address.java
new file mode 100644
index 0000000..ec7d5b3
--- /dev/null
+++ b/src/main/java/com/azure/cosmos/examples/common/Address.java
@@ -0,0 +1,35 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.cosmos.examples.common;
+
+public class Address {
+ public String getState() {
+ return state;
+ }
+
+ public void setState(String state) {
+ this.state = state;
+ }
+
+ public String getCounty() {
+ return county;
+ }
+
+ public void setCounty(String county) {
+ this.county = county;
+ }
+
+ public String getCity() {
+ return city;
+ }
+
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+ private String state;
+ private String county;
+ private String city;
+}
+
diff --git a/src/main/java/com/azure/cosmos/examples/common/Child.java b/src/main/java/com/azure/cosmos/examples/common/Child.java
new file mode 100644
index 0000000..98cdd5c
--- /dev/null
+++ b/src/main/java/com/azure/cosmos/examples/common/Child.java
@@ -0,0 +1,53 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.cosmos.examples.common;
+
+public class Child {
+ public String getFamilyName() {
+ return familyName;
+ }
+
+ public void setFamilyName(String familyName) {
+ this.familyName = familyName;
+ }
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+ public String getGender() {
+ return gender;
+ }
+
+ public void setGender(String gender) {
+ this.gender = gender;
+ }
+
+ public int getGrade() {
+ return grade;
+ }
+
+ public void setGrade(int grade) {
+ this.grade = grade;
+ }
+
+ public Pet[] getPets() {
+ return pets;
+ }
+
+ public void setPets(Pet[] pets) {
+ this.pets = pets;
+ }
+
+ private String familyName;
+ private String firstName;
+ private String gender;
+ private int grade;
+ private Pet[] pets;
+}
+
diff --git a/src/main/java/com/azure/cosmos/examples/common/CustomPOJO.java b/src/main/java/com/azure/cosmos/examples/common/CustomPOJO.java
new file mode 100644
index 0000000..0341d1a
--- /dev/null
+++ b/src/main/java/com/azure/cosmos/examples/common/CustomPOJO.java
@@ -0,0 +1,24 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.cosmos.examples.common;
+
+public class CustomPOJO {
+ private String id;
+
+ public CustomPOJO() {
+
+ }
+
+ public CustomPOJO(String id) {
+ this.id = id;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+}
diff --git a/src/main/java/com/azure/cosmos/examples/common/Families.java b/src/main/java/com/azure/cosmos/examples/common/Families.java
new file mode 100644
index 0000000..1f658ae
--- /dev/null
+++ b/src/main/java/com/azure/cosmos/examples/common/Families.java
@@ -0,0 +1,117 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.cosmos.examples.common;
+
+public class Families {
+
+ public static Family getAndersenFamilyItem() {
+ Family andersenFamily = new Family();
+ andersenFamily.setId("Andersen-" + System.currentTimeMillis());
+ andersenFamily.setLastName("Andersen");
+
+ Parent parent1 = new Parent();
+ parent1.setFirstName("Thomas");
+
+ Parent parent2 = new Parent();
+ parent2.setFirstName("Mary Kay");
+
+ andersenFamily.setParents(new Parent[]{parent1, parent2});
+
+ Child child1 = new Child();
+ child1.setFirstName("Henriette Thaulow");
+ child1.setGender("female");
+ child1.setGrade(5);
+
+ Pet pet1 = new Pet();
+ pet1.setGivenName("Fluffy");
+
+ child1.setPets(new Pet[]{pet1});
+
+ andersenFamily.setDistrict("WA5");
+ Address address = new Address();
+ address.setCity("Seattle");
+ address.setCounty("King");
+ address.setState("WA");
+
+ andersenFamily.setAddress(address);
+ andersenFamily.setRegistered(true);
+
+ return andersenFamily;
+ }
+
+ public static Family getWakefieldFamilyItem() {
+ Family wakefieldFamily = new Family();
+ wakefieldFamily.setId("Wakefield-" + System.currentTimeMillis());
+ wakefieldFamily.setLastName("Wakefield");
+
+ Parent parent1 = new Parent();
+ parent1.setFamilyName("Wakefield");
+ parent1.setFirstName("Robin");
+
+ Parent parent2 = new Parent();
+ parent2.setFamilyName("Miller");
+ parent2.setFirstName("Ben");
+
+ wakefieldFamily.setParents(new Parent[]{parent1, parent2});
+
+ Child child1 = new Child();
+ child1.setFirstName("Jesse");
+ child1.setFamilyName("Merriam");
+ child1.setGrade(8);
+
+ Pet pet1 = new Pet();
+ pet1.setGivenName("Goofy");
+
+ Pet pet2 = new Pet();
+ pet2.setGivenName("Shadow");
+
+ child1.setPets(new Pet[]{pet1, pet2});
+
+ Child child2 = new Child();
+ child2.setFirstName("Lisa");
+ child2.setFamilyName("Miller");
+ child2.setGrade(1);
+ child2.setGender("female");
+
+ wakefieldFamily.setChildren(new Child[]{child1, child2});
+
+ Address address = new Address();
+ address.setCity("NY");
+ address.setCounty("Manhattan");
+ address.setState("NY");
+
+ wakefieldFamily.setAddress(address);
+ wakefieldFamily.setDistrict("NY23");
+ wakefieldFamily.setRegistered(true);
+ return wakefieldFamily;
+ }
+
+ public static Family getJohnsonFamilyItem() {
+ Family andersenFamily = new Family();
+ andersenFamily.setId("Johnson-" + System.currentTimeMillis());
+ andersenFamily.setLastName("Johnson");
+
+ Parent parent1 = new Parent();
+ parent1.setFirstName("John");
+
+ Parent parent2 = new Parent();
+ parent2.setFirstName("Lili");
+
+ return andersenFamily;
+ }
+
+ public static Family getSmithFamilyItem() {
+ Family andersenFamily = new Family();
+ andersenFamily.setId("Smith-" + System.currentTimeMillis());
+ andersenFamily.setLastName("Smith");
+
+ Parent parent1 = new Parent();
+ parent1.setFirstName("John");
+
+ Parent parent2 = new Parent();
+ parent2.setFirstName("Cynthia");
+
+ return andersenFamily;
+ }
+}
diff --git a/src/main/java/com/azure/cosmos/examples/common/Family.java b/src/main/java/com/azure/cosmos/examples/common/Family.java
new file mode 100644
index 0000000..4e337b3
--- /dev/null
+++ b/src/main/java/com/azure/cosmos/examples/common/Family.java
@@ -0,0 +1,74 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.cosmos.examples.common;
+
+public class Family {
+ public Family() {
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+
+ public String getDistrict() {
+ return district;
+ }
+
+ public void setDistrict(String district) {
+ this.district = district;
+ }
+
+ public Parent[] getParents() {
+ return parents;
+ }
+
+ public void setParents(Parent[] parents) {
+ this.parents = parents;
+ }
+
+ public Child[] getChildren() {
+ return children;
+ }
+
+ public void setChildren(Child[] children) {
+ this.children = children;
+ }
+
+ public Address getAddress() {
+ return address;
+ }
+
+ public void setAddress(Address address) {
+ this.address = address;
+ }
+
+ public boolean isRegistered() {
+ return isRegistered;
+ }
+
+ public void setRegistered(boolean isRegistered) {
+ this.isRegistered = isRegistered;
+ }
+
+ private String id;
+ private String lastName;
+ private String district;
+ private Parent[] parents;
+ private Child[] children;
+ private Address address;
+ private boolean isRegistered;
+}
+
diff --git a/src/main/java/com/azure/cosmos/examples/common/Parent.java b/src/main/java/com/azure/cosmos/examples/common/Parent.java
new file mode 100644
index 0000000..d7753a8
--- /dev/null
+++ b/src/main/java/com/azure/cosmos/examples/common/Parent.java
@@ -0,0 +1,33 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.cosmos.examples.common;
+
+public class Parent {
+
+ public Parent() {
+ }
+
+ public Parent(String firstName) {
+ this.firstName = firstName;
+ }
+
+ public String getFamilyName() {
+ return familyName;
+ }
+
+ public void setFamilyName(String familyName) {
+ this.familyName = familyName;
+ }
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+ private String familyName;
+ private String firstName;
+}
diff --git a/src/main/java/com/azure/cosmos/examples/common/Pet.java b/src/main/java/com/azure/cosmos/examples/common/Pet.java
new file mode 100644
index 0000000..062ce93
--- /dev/null
+++ b/src/main/java/com/azure/cosmos/examples/common/Pet.java
@@ -0,0 +1,16 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.cosmos.examples.common;
+
+public class Pet {
+ public String getGivenName() {
+ return givenName;
+ }
+
+ public void setGivenName(String givenName) {
+ this.givenName = givenName;
+ }
+
+ private String givenName;
+}
diff --git a/src/main/java/com/azure/cosmos/examples/crudquickstart/async/SampleCRUDQuickstartAsync.java b/src/main/java/com/azure/cosmos/examples/crudquickstart/async/SampleCRUDQuickstartAsync.java
new file mode 100644
index 0000000..379ee18
--- /dev/null
+++ b/src/main/java/com/azure/cosmos/examples/crudquickstart/async/SampleCRUDQuickstartAsync.java
@@ -0,0 +1,359 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.cosmos.examples.crudquickstart.async;
+
+
+import com.azure.cosmos.ConnectionPolicy;
+import com.azure.cosmos.ConsistencyLevel;
+import com.azure.cosmos.CosmosAsyncClient;
+import com.azure.cosmos.CosmosAsyncContainer;
+import com.azure.cosmos.CosmosAsyncDatabase;
+import com.azure.cosmos.CosmosClientBuilder;
+import com.azure.cosmos.CosmosClientException;
+import com.azure.cosmos.CosmosPagedFlux;
+import com.azure.cosmos.examples.changefeed.SampleChangeFeedProcessor;
+import com.azure.cosmos.examples.common.AccountSettings;
+import com.azure.cosmos.examples.common.Families;
+import com.azure.cosmos.examples.common.Family;
+import com.azure.cosmos.models.CosmosAsyncContainerResponse;
+import com.azure.cosmos.models.CosmosAsyncDatabaseResponse;
+import com.azure.cosmos.models.CosmosAsyncItemResponse;
+import com.azure.cosmos.models.CosmosContainerProperties;
+import com.azure.cosmos.models.FeedOptions;
+import com.azure.cosmos.models.PartitionKey;
+import com.google.common.collect.Lists;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import java.time.Duration;
+import java.util.concurrent.CountDownLatch;
+import java.util.stream.Collectors;
+
+public class SampleCRUDQuickstartAsync {
+
+ private CosmosAsyncClient client;
+
+ private final String databaseName = "AzureSampleFamilyDB";
+ private final String containerName = "FamilyContainer";
+
+ private CosmosAsyncDatabase database;
+ private CosmosAsyncContainer container;
+
+ protected static Logger logger = LoggerFactory.getLogger(SampleChangeFeedProcessor.class.getSimpleName());
+
+ public void close() {
+ client.close();
+ }
+
+ /**
+ * Run a Hello CosmosDB console application.
+ *
+ * This is a simple sample application intended to demonstrate Create, Read, Update, Delete (CRUD) operations
+ * with Azure Cosmos DB Java SDK, as applied to databases, containers and items. This sample will
+ * 1. Create asynchronous client, database and container instances
+ * 2. Create several items
+ * 3. Upsert one of the items
+ * 4. Perform a query over the items
+ * 5. Delete an item
+ * 6. Delete the Cosmos DB database and container resources and close the client.
+ */
+ //
+ public static void main(String[] args) {
+ SampleCRUDQuickstartAsync p = new SampleCRUDQuickstartAsync();
+
+ try {
+ logger.info("Starting ASYNC main");
+ p.getStartedDemo();
+ logger.info("Demo complete, please hold while resources are released");
+ } catch (Exception e) {
+ e.printStackTrace();
+ logger.error(String.format("Cosmos getStarted failed with %s", e));
+ } finally {
+ logger.info("Closing the client");
+ p.shutdown();
+ }
+ }
+
+ //
+
+ private void getStartedDemo() throws Exception {
+
+ logger.info("Using Azure Cosmos DB endpoint: " + AccountSettings.HOST);
+
+ ConnectionPolicy defaultPolicy = ConnectionPolicy.getDefaultPolicy();
+ // Setting the preferred location to Cosmos DB Account region
+ // West US is just an example. User should set preferred location to the Cosmos DB region closest to the application
+ defaultPolicy.setPreferredLocations(Lists.newArrayList("West US"));
+
+ // Create async client
+ //
+ client = new CosmosClientBuilder()
+ .setEndpoint(AccountSettings.HOST)
+ .setKey(AccountSettings.MASTER_KEY)
+ .setConnectionPolicy(defaultPolicy)
+ .setConsistencyLevel(ConsistencyLevel.EVENTUAL)
+ .buildAsyncClient();
+
+ //
+
+ createDatabaseIfNotExists();
+ createContainerIfNotExists();
+
+ Family andersenFamilyItem = Families.getAndersenFamilyItem();
+ Family wakefieldFamilyItem = Families.getWakefieldFamilyItem();
+ Family johnsonFamilyItem = Families.getJohnsonFamilyItem();
+ Family smithFamilyItem = Families.getSmithFamilyItem();
+
+ // Setup family items to create
+ Flux familiesToCreate = Flux.just(andersenFamilyItem,
+ wakefieldFamilyItem,
+ johnsonFamilyItem,
+ smithFamilyItem);
+
+ // Creates several items in the container
+ createFamilies(familiesToCreate);
+
+ // Upsert one of the items in the container
+ upsertFamily(wakefieldFamilyItem);
+
+ familiesToCreate = Flux.just(andersenFamilyItem,
+ wakefieldFamilyItem,
+ johnsonFamilyItem,
+ smithFamilyItem);
+
+ logger.info("Reading items.");
+ readItems(familiesToCreate);
+
+ logger.info("Querying items.");
+ queryItems();
+
+ logger.info("Deleting an item.");
+ deleteItem(andersenFamilyItem);
+ }
+
+ private void createDatabaseIfNotExists() throws Exception {
+ logger.info("Create database " + databaseName + " if not exists.");
+
+ // Create database if not exists
+ //
+ Mono databaseIfNotExists = client.createDatabaseIfNotExists(databaseName);
+ databaseIfNotExists.flatMap(databaseResponse -> {
+ database = databaseResponse.getDatabase();
+ logger.info("Checking database " + database.getId() + " completed!\n");
+ return Mono.empty();
+ }).block();
+ //
+ }
+
+ private void createContainerIfNotExists() throws Exception {
+ logger.info("Create container " + containerName + " if not exists.");
+
+ // Create container if not exists
+ //
+
+ CosmosContainerProperties containerProperties = new CosmosContainerProperties(containerName, "/lastName");
+ Mono containerIfNotExists = database.createContainerIfNotExists(containerProperties, 400);
+
+ // Create container with 400 RU/s
+ containerIfNotExists.flatMap(containerResponse -> {
+ container = containerResponse.getContainer();
+ logger.info("Checking container " + container.getId() + " completed!\n");
+ return Mono.empty();
+ }).block();
+
+ //
+ }
+
+ private void createFamilies(Flux families) throws Exception {
+
+ //
+
+ final CountDownLatch completionLatch = new CountDownLatch(1);
+
+ // Combine multiple item inserts, associated success println's, and a final aggregate stats println into one Reactive stream.
+ families.flatMap(family -> {
+ return container.createItem(family);
+ }) //Flux of item request responses
+ .flatMap(itemResponse -> {
+ logger.info(String.format("Created item with request charge of %.2f within" +
+ " duration %s",
+ itemResponse.getRequestCharge(), itemResponse.getRequestLatency()));
+ logger.info(String.format("Item ID: %s\n", itemResponse.getItem().getId()));
+ return Mono.just(itemResponse.getRequestCharge());
+ }) //Flux of request charges
+ .reduce(0.0,
+ (charge_n, charge_nplus1) -> charge_n + charge_nplus1
+ ) //Mono of total charge - there will be only one item in this stream
+ .subscribe(charge -> {
+ logger.info(String.format("Created items with total request charge of %.2f\n",
+ charge));
+ },
+ err -> {
+ if (err instanceof CosmosClientException) {
+ //Client-specific errors
+ CosmosClientException cerr = (CosmosClientException) err;
+ cerr.printStackTrace();
+ logger.error(String.format("Read Item failed with %s\n", cerr));
+ } else {
+ //General errors
+ err.printStackTrace();
+ }
+
+ completionLatch.countDown();
+ },
+ () -> {
+ completionLatch.countDown();
+ }
+ ); //Preserve the total charge and print aggregate charge/item count stats.
+
+ try {
+ completionLatch.await();
+ } catch (InterruptedException err) {
+ throw new AssertionError("Unexpected Interruption", err);
+ }
+
+ //
+ }
+
+ private void upsertFamily(Family family_to_upsert) {
+ //Modify a field of the family object
+ logger.info(String.format("Upserting the item with id %s after modifying the isRegistered field...", family_to_upsert.getId()));
+ family_to_upsert.setRegistered(!family_to_upsert.isRegistered());
+
+ //Upsert the modified item
+ Mono.just(family_to_upsert).flatMap(item -> {
+ CosmosAsyncItemResponse item_resp = container.upsertItem(family_to_upsert).block();
+
+ // Get upsert request charge and other properties like latency, and diagnostics strings, etc.
+ logger.info(String.format("Upserted item with request charge of %.2f within duration %s",
+ item_resp.getRequestCharge(), item_resp.getRequestLatency()));
+
+ return Mono.empty();
+ }).subscribe();
+ }
+
+ private void readItems(Flux familiesToCreate) {
+ // Using partition key for point read scenarios.
+ // This will help fast look up of items because of partition key
+ //
+
+ final CountDownLatch completionLatch = new CountDownLatch(1);
+
+ familiesToCreate.flatMap(family -> {
+ Mono> asyncItemResponseMono = container.readItem(family.getId(), new PartitionKey(family.getLastName()), Family.class);
+ return asyncItemResponseMono;
+ })
+ .subscribe(
+ itemResponse -> {
+ double requestCharge = itemResponse.getRequestCharge();
+ Duration requestLatency = itemResponse.getRequestLatency();
+ logger.info(String.format("Item successfully read with id %s with a charge of %.2f and within duration %s",
+ itemResponse.getItem().getId(), requestCharge, requestLatency));
+ },
+ err -> {
+ if (err instanceof CosmosClientException) {
+ //Client-specific errors
+ CosmosClientException cerr = (CosmosClientException) err;
+ cerr.printStackTrace();
+ logger.error(String.format("Read Item failed with %s\n", cerr));
+ } else {
+ //General errors
+ err.printStackTrace();
+ }
+
+ completionLatch.countDown();
+ },
+ () -> {
+ completionLatch.countDown();
+ }
+ );
+
+ try {
+ completionLatch.await();
+ } catch (InterruptedException err) {
+ throw new AssertionError("Unexpected Interruption", err);
+ }
+
+ //
+ }
+
+ private void queryItems() {
+ //
+ // Set some common query options
+
+ FeedOptions queryOptions = new FeedOptions();
+ queryOptions.setMaxItemCount(10);
+ //queryOptions.setEnableCrossPartitionQuery(true); //No longer needed in SDK v4
+ // Set populate query metrics to get metrics around query executions
+ queryOptions.setPopulateQueryMetrics(true);
+
+ CosmosPagedFlux pagedFluxResponse = container.queryItems(
+ "SELECT * FROM Family WHERE Family.lastName IN ('Andersen', 'Wakefield', 'Johnson')", queryOptions, Family.class);
+
+ final CountDownLatch completionLatch = new CountDownLatch(1);
+
+ pagedFluxResponse.byPage().subscribe(
+ fluxResponse -> {
+ logger.info("Got a page of query result with " +
+ fluxResponse.getResults().size() + " items(s)"
+ + " and request charge of " + fluxResponse.getRequestCharge());
+
+ logger.info("Item Ids " + fluxResponse
+ .getResults()
+ .stream()
+ .map(Family::getId)
+ .collect(Collectors.toList()));
+ },
+ err -> {
+ if (err instanceof CosmosClientException) {
+ //Client-specific errors
+ CosmosClientException cerr = (CosmosClientException) err;
+ cerr.printStackTrace();
+ logger.error(String.format("Read Item failed with %s\n", cerr));
+ } else {
+ //General errors
+ err.printStackTrace();
+ }
+
+ completionLatch.countDown();
+ },
+ () -> {
+ completionLatch.countDown();
+ }
+ );
+
+ try {
+ completionLatch.await();
+ } catch (InterruptedException err) {
+ throw new AssertionError("Unexpected Interruption", err);
+ }
+
+ //
+ }
+
+ private void deleteItem(Family item) {
+ container.deleteItem(item.getId(), new PartitionKey(item.getLastName())).block();
+ }
+
+ private void shutdown() {
+ try {
+ //Clean shutdown
+ logger.info("Deleting Cosmos DB resources");
+ logger.info("-Deleting container...");
+ if (container != null)
+ container.delete().subscribe();
+ logger.info("-Deleting database...");
+ if (database != null)
+ database.delete().subscribe();
+ logger.info("-Closing the client...");
+ } catch (Exception err) {
+ logger.error("Deleting Cosmos DB resources failed, will still attempt to close the client. See stack trace below.");
+ err.printStackTrace();
+ }
+ client.close();
+ logger.info("Done.");
+ }
+}
diff --git a/src/main/java/com/azure/cosmos/examples/crudquickstart/sync/SampleCRUDQuickstart.java b/src/main/java/com/azure/cosmos/examples/crudquickstart/sync/SampleCRUDQuickstart.java
new file mode 100644
index 0000000..0659d25
--- /dev/null
+++ b/src/main/java/com/azure/cosmos/examples/crudquickstart/sync/SampleCRUDQuickstart.java
@@ -0,0 +1,249 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.cosmos.examples.crudquickstart.sync;
+
+import com.azure.cosmos.ConnectionPolicy;
+import com.azure.cosmos.ConsistencyLevel;
+import com.azure.cosmos.CosmosClient;
+import com.azure.cosmos.CosmosClientBuilder;
+import com.azure.cosmos.CosmosClientException;
+import com.azure.cosmos.CosmosContainer;
+import com.azure.cosmos.CosmosDatabase;
+import com.azure.cosmos.CosmosPagedIterable;
+import com.azure.cosmos.examples.changefeed.SampleChangeFeedProcessor;
+import com.azure.cosmos.examples.common.AccountSettings;
+import com.azure.cosmos.examples.common.Families;
+import com.azure.cosmos.examples.common.Family;
+import com.azure.cosmos.models.CosmosContainerProperties;
+import com.azure.cosmos.models.CosmosItemRequestOptions;
+import com.azure.cosmos.models.CosmosItemResponse;
+import com.azure.cosmos.models.FeedOptions;
+import com.azure.cosmos.models.PartitionKey;
+import com.google.common.collect.Lists;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class SampleCRUDQuickstart {
+
+ private CosmosClient client;
+
+ private final String databaseName = "AzureSampleFamilyDB";
+ private final String containerName = "FamilyContainer";
+
+ private CosmosDatabase database;
+ private CosmosContainer container;
+
+ protected static Logger logger = LoggerFactory.getLogger(SampleChangeFeedProcessor.class.getSimpleName());
+
+ public void close() {
+ client.close();
+ }
+
+ /**
+ * Run a Hello CosmosDB console application.
+ *
+ * This is a simple sample application intended to demonstrate Create, Read, Update, Delete (CRUD) operations
+ * with Azure Cosmos DB Java SDK, as applied to databases, containers and items. This sample will
+ * 1. Create synchronous client, database and container instances
+ * 2. Create several items
+ * 3. Upsert one of the items
+ * 4. Perform a query over the items
+ * 5. Delete an item
+ * 6. Delete the Cosmos DB database and container resources and close the client. *
+ */
+ //
+ public static void main(String[] args) {
+ SampleCRUDQuickstart p = new SampleCRUDQuickstart();
+
+ try {
+ logger.info("Starting SYNC main");
+ p.getStartedDemo();
+ logger.info("Demo complete, please hold while resources are released");
+ } catch (Exception e) {
+ e.printStackTrace();
+ logger.error(String.format("Cosmos getStarted failed with %s", e));
+ } finally {
+ logger.info("Closing the client");
+ p.shutdown();
+ }
+ }
+
+ //
+
+ private void getStartedDemo() throws Exception {
+
+ logger.info("Using Azure Cosmos DB endpoint: " + AccountSettings.HOST);
+
+ ConnectionPolicy defaultPolicy = ConnectionPolicy.getDefaultPolicy();
+ // Setting the preferred location to Cosmos DB Account region
+ // West US is just an example. User should set preferred location to the Cosmos DB region closest to the application
+ defaultPolicy.setPreferredLocations(Lists.newArrayList("West US"));
+
+ // Create sync client
+ //
+ client = new CosmosClientBuilder()
+ .setEndpoint(AccountSettings.HOST)
+ .setKey(AccountSettings.MASTER_KEY)
+ .setConnectionPolicy(defaultPolicy)
+ .setConsistencyLevel(ConsistencyLevel.EVENTUAL)
+ .buildClient();
+
+ //
+
+ createDatabaseIfNotExists();
+ createContainerIfNotExists();
+
+ // Setup family items to create
+ ArrayList familiesToCreate = new ArrayList<>();
+ familiesToCreate.add(Families.getAndersenFamilyItem());
+ familiesToCreate.add(Families.getWakefieldFamilyItem());
+ familiesToCreate.add(Families.getJohnsonFamilyItem());
+ familiesToCreate.add(Families.getSmithFamilyItem());
+
+ // Creates several items in the container
+ // Also applies an upsert operation to one of the items (create if not present, otherwise replace)
+ createFamilies(familiesToCreate);
+
+ logger.info("Reading items.");
+ readItems(familiesToCreate);
+
+ logger.info("Querying items.");
+ queryItems();
+
+ logger.info("Delete an item.");
+ deleteItem(familiesToCreate.get(0));
+ }
+
+ private void createDatabaseIfNotExists() throws Exception {
+ logger.info("Create database " + databaseName + " if not exists.");
+
+ // Create database if not exists
+ //
+ database = client.createDatabaseIfNotExists(databaseName).getDatabase();
+ //
+
+ logger.info("Checking database " + database.getId() + " completed!\n");
+ }
+
+ private void createContainerIfNotExists() throws Exception {
+ logger.info("Create container " + containerName + " if not exists.");
+
+ // Create container if not exists
+ //
+ CosmosContainerProperties containerProperties =
+ new CosmosContainerProperties(containerName, "/lastName");
+
+ // Create container with 400 RU/s
+ container = database.createContainerIfNotExists(containerProperties, 400).getContainer();
+ //
+
+ logger.info("Checking container " + container.getId() + " completed!\n");
+ }
+
+ private void createFamilies(List families) throws Exception {
+ double totalRequestCharge = 0;
+ for (Family family : families) {
+
+ //
+ // Create item using container that we created using sync client
+
+ // Use lastName as partitionKey for cosmos item
+ // Using appropriate partition key improves the performance of database operations
+ CosmosItemRequestOptions cosmosItemRequestOptions = new CosmosItemRequestOptions();
+ CosmosItemResponse item = container.createItem(family, new PartitionKey(family.getLastName()), cosmosItemRequestOptions);
+ //
+
+ // Get request charge and other properties like latency, and diagnostics strings, etc.
+ logger.info(String.format("Created item with request charge of %.2f within duration %s",
+ item.getRequestCharge(), item.getRequestLatency()));
+
+ totalRequestCharge += item.getRequestCharge();
+ }
+ logger.info(String.format("Created %d items with total request charge of %.2f",
+ families.size(), totalRequestCharge));
+
+ Family family_to_upsert = families.get(0);
+ logger.info(String.format("Upserting the item with id %s after modifying the isRegistered field...", family_to_upsert.getId()));
+ family_to_upsert.setRegistered(!family_to_upsert.isRegistered());
+
+ CosmosItemResponse item = container.upsertItem(family_to_upsert);
+
+ // Get upsert request charge and other properties like latency, and diagnostics strings, etc.
+ logger.info(String.format("Upserted item with request charge of %.2f within duration %s",
+ item.getRequestCharge(), item.getRequestLatency()));
+ }
+
+ private void readItems(ArrayList familiesToCreate) {
+ // Using partition key for point read scenarios.
+ // This will help fast look up of items because of partition key
+ familiesToCreate.forEach(family -> {
+ //
+ try {
+ CosmosItemResponse item = container.readItem(family.getId(), new PartitionKey(family.getLastName()), Family.class);
+ double requestCharge = item.getRequestCharge();
+ Duration requestLatency = item.getRequestLatency();
+ logger.info(String.format("Item successfully read with id %s with a charge of %.2f and within duration %s",
+ item.getResource().getId(), requestCharge, requestLatency));
+ } catch (CosmosClientException e) {
+ e.printStackTrace();
+ logger.info(String.format("Read Item failed with %s", e));
+ }
+ //
+ });
+ }
+
+ private void queryItems() {
+ //
+ // Set some common query options
+ FeedOptions queryOptions = new FeedOptions();
+ queryOptions.setMaxItemCount(10);
+ //queryOptions.setEnableCrossPartitionQuery(true); //No longer necessary in SDK v4
+ // Set populate query metrics to get metrics around query executions
+ queryOptions.setPopulateQueryMetrics(true);
+
+ CosmosPagedIterable familiesPagedIterable = container.queryItems(
+ "SELECT * FROM Family WHERE Family.lastName IN ('Andersen', 'Wakefield', 'Johnson')", queryOptions, Family.class);
+
+ familiesPagedIterable.iterableByPage().forEach(cosmosItemPropertiesFeedResponse -> {
+ logger.info("Got a page of query result with " +
+ cosmosItemPropertiesFeedResponse.getResults().size() + " items(s)"
+ + " and request charge of " + cosmosItemPropertiesFeedResponse.getRequestCharge());
+
+ logger.info("Item Ids " + cosmosItemPropertiesFeedResponse
+ .getResults()
+ .stream()
+ .map(Family::getId)
+ .collect(Collectors.toList()));
+ });
+ //
+ }
+
+ private void deleteItem(Family item) {
+ container.deleteItem(item.getId(), new PartitionKey(item.getLastName()), new CosmosItemRequestOptions());
+ }
+
+ private void shutdown() {
+ try {
+ //Clean shutdown
+ logger.info("Deleting Cosmos DB resources");
+ logger.info("-Deleting container...");
+ if (container != null)
+ container.delete();
+ logger.info("-Deleting database...");
+ if (database != null)
+ database.delete();
+ logger.info("-Closing the client...");
+ } catch (Exception err) {
+ logger.error("Deleting Cosmos DB resources failed, will still attempt to close the client. See stack trace below.");
+ err.printStackTrace();
+ }
+ client.close();
+ logger.info("Done.");
+ }
+}
diff --git a/src/main/java/com/azure/cosmos/examples/indexmanagement/async/SampleIndexManagementAsync.java b/src/main/java/com/azure/cosmos/examples/indexmanagement/async/SampleIndexManagementAsync.java
new file mode 100644
index 0000000..34628ff
--- /dev/null
+++ b/src/main/java/com/azure/cosmos/examples/indexmanagement/async/SampleIndexManagementAsync.java
@@ -0,0 +1,389 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.cosmos.examples.indexmanagement.async;
+
+import com.azure.cosmos.ConnectionPolicy;
+import com.azure.cosmos.ConsistencyLevel;
+import com.azure.cosmos.CosmosAsyncClient;
+import com.azure.cosmos.CosmosAsyncContainer;
+import com.azure.cosmos.CosmosAsyncDatabase;
+import com.azure.cosmos.CosmosClientBuilder;
+import com.azure.cosmos.CosmosClientException;
+import com.azure.cosmos.CosmosPagedFlux;
+import com.azure.cosmos.examples.changefeed.SampleChangeFeedProcessor;
+import com.azure.cosmos.examples.common.AccountSettings;
+import com.azure.cosmos.examples.common.Families;
+import com.azure.cosmos.examples.common.Family;
+import com.azure.cosmos.models.CosmosAsyncContainerResponse;
+import com.azure.cosmos.models.CosmosAsyncDatabaseResponse;
+import com.azure.cosmos.models.CosmosAsyncItemResponse;
+import com.azure.cosmos.models.CosmosContainerProperties;
+import com.azure.cosmos.models.ExcludedPath;
+import com.azure.cosmos.models.FeedOptions;
+import com.azure.cosmos.models.IncludedPath;
+import com.azure.cosmos.models.IndexingMode;
+import com.azure.cosmos.models.IndexingPolicy;
+import com.azure.cosmos.models.PartitionKey;
+import com.google.common.collect.Lists;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.stream.Collectors;
+
+public class SampleIndexManagementAsync {
+
+ private CosmosAsyncClient client;
+
+ private final String databaseName = "AzureSampleFamilyDB";
+ private final String containerName = "FamilyContainer";
+
+ private CosmosAsyncDatabase database;
+ private CosmosAsyncContainer container;
+
+ protected static Logger logger = LoggerFactory.getLogger(SampleChangeFeedProcessor.class.getSimpleName());
+
+ public void close() {
+ client.close();
+ }
+
+ /**
+ * Run a Hello CosmosDB console application.
+ *
+ * This sample is similar to SampleCRUDQuickstartAsync, but modified to show indexing capabilities of Cosmos DB.
+ * Look at the implementation of createContainerIfNotExistsWithSpecifiedIndex() for the demonstration of
+ * indexing capabilities.
+ */
+ //
+ public static void main(String[] args) {
+ SampleIndexManagementAsync p = new SampleIndexManagementAsync();
+
+ try {
+ logger.info("Starting ASYNC main");
+ p.indexManagementDemo();
+ logger.info("Demo complete, please hold while resources are released");
+ } catch (Exception e) {
+ e.printStackTrace();
+ logger.error(String.format("Cosmos getStarted failed with %s", e));
+ } finally {
+ logger.info("Closing the client");
+ p.shutdown();
+ }
+ }
+
+ //
+
+ private void indexManagementDemo() throws Exception {
+
+ logger.info("Using Azure Cosmos DB endpoint: " + AccountSettings.HOST);
+
+ ConnectionPolicy defaultPolicy = ConnectionPolicy.getDefaultPolicy();
+ // Setting the preferred location to Cosmos DB Account region
+ // West US is just an example. User should set preferred location to the Cosmos DB region closest to the application
+ defaultPolicy.setPreferredLocations(Lists.newArrayList("West US"));
+
+ // Create async client
+ //
+ client = new CosmosClientBuilder()
+ .setEndpoint(AccountSettings.HOST)
+ .setKey(AccountSettings.MASTER_KEY)
+ .setConnectionPolicy(defaultPolicy)
+ .setConsistencyLevel(ConsistencyLevel.EVENTUAL)
+ .buildAsyncClient();
+
+ //
+
+ createDatabaseIfNotExists();
+
+ //Here is where index management is performed
+ createContainerIfNotExistsWithSpecifiedIndex();
+
+ Family andersenFamilyItem = Families.getAndersenFamilyItem();
+ Family wakefieldFamilyItem = Families.getWakefieldFamilyItem();
+ Family johnsonFamilyItem = Families.getJohnsonFamilyItem();
+ Family smithFamilyItem = Families.getSmithFamilyItem();
+
+ // Setup family items to create
+ Flux familiesToCreate = Flux.just(andersenFamilyItem,
+ wakefieldFamilyItem,
+ johnsonFamilyItem,
+ smithFamilyItem);
+
+ createFamilies(familiesToCreate);
+
+ familiesToCreate = Flux.just(andersenFamilyItem,
+ wakefieldFamilyItem,
+ johnsonFamilyItem,
+ smithFamilyItem);
+
+ logger.info("Reading items.");
+ readItems(familiesToCreate);
+
+ logger.info("Querying items.");
+ queryItems();
+ }
+
+ private void createDatabaseIfNotExists() throws Exception {
+ logger.info("Create database " + databaseName + " if not exists.");
+
+ // Create database if not exists
+ //
+ Mono databaseIfNotExists = client.createDatabaseIfNotExists(databaseName);
+ databaseIfNotExists.flatMap(databaseResponse -> {
+ database = databaseResponse.getDatabase();
+ logger.info("Checking database " + database.getId() + " completed!\n");
+ return Mono.empty();
+ }).block();
+ //
+ }
+
+ private void createContainerIfNotExistsWithSpecifiedIndex() throws Exception {
+ logger.info("Create container " + containerName + " if not exists.");
+
+ // Create container if not exists
+ //
+
+ CosmosContainerProperties containerProperties = new CosmosContainerProperties(containerName, "/lastName");
+
+ //
+ IndexingPolicy indexingPolicy = new IndexingPolicy();
+ indexingPolicy.setIndexingMode(IndexingMode.CONSISTENT); //To turn indexing off set IndexingMode.NONE
+
+ // Included paths
+ List includedPaths = new ArrayList<>();
+ IncludedPath includedPath = new IncludedPath();
+ includedPath.setPath("/*");
+ includedPaths.add(includedPath);
+ indexingPolicy.setIncludedPaths(includedPaths);
+
+ // Excluded paths
+ List excludedPaths = new ArrayList<>();
+ ExcludedPath excludedPath = new ExcludedPath();
+ excludedPath.setPath("/name/*");
+ excludedPaths.add(excludedPath);
+ indexingPolicy.setExcludedPaths(excludedPaths);
+
+ // Spatial indices - if you need them, here is how to set them up:
+ /*
+ List spatialIndexes = new ArrayList();
+ List collectionOfSpatialTypes = new ArrayList();
+
+ SpatialSpec spec = new SpatialSpec();
+ spec.setPath("/locations/*");
+ collectionOfSpatialTypes.add(SpatialType.Point);
+ spec.setSpatialTypes(collectionOfSpatialTypes);
+ spatialIndexes.add(spec);
+
+ indexingPolicy.setSpatialIndexes(spatialIndexes);
+ */
+
+ // Composite indices - if you need them, here is how to set them up:
+ /*
+ List> compositeIndexes = new ArrayList<>();
+ List compositePaths = new ArrayList<>();
+
+ CompositePath nameCompositePath = new CompositePath();
+ nameCompositePath.setPath("/name");
+ nameCompositePath.setOrder(CompositePathSortOrder.ASCENDING);
+
+ CompositePath ageCompositePath = new CompositePath();
+ ageCompositePath.setPath("/age");
+ ageCompositePath.setOrder(CompositePathSortOrder.DESCENDING);
+
+ compositePaths.add(ageCompositePath);
+ compositePaths.add(nameCompositePath);
+
+ compositeIndexes.add(compositePaths);
+ indexingPolicy.setCompositeIndexes(compositeIndexes);
+ */
+
+ containerProperties.setIndexingPolicy(indexingPolicy);
+
+ //
+
+ Mono containerIfNotExists = database.createContainerIfNotExists(containerProperties, 400);
+
+ // Create container with 400 RU/s
+ containerIfNotExists.flatMap(containerResponse -> {
+ container = containerResponse.getContainer();
+ logger.info("Checking container " + container.getId() + " completed!\n");
+ return Mono.empty();
+ }).block();
+
+ //
+ }
+
+ private void createFamilies(Flux families) throws Exception {
+
+ //
+
+ final CountDownLatch completionLatch = new CountDownLatch(1);
+
+ // Combine multiple item inserts, associated success println's, and a final aggregate stats println into one Reactive stream.
+ families.flatMap(family -> {
+ return container.createItem(family);
+ }) //Flux of item request responses
+ .flatMap(itemResponse -> {
+ logger.info(String.format("Created item with request charge of %.2f within" +
+ " duration %s",
+ itemResponse.getRequestCharge(), itemResponse.getRequestLatency()));
+ logger.info(String.format("Item ID: %s\n", itemResponse.getItem().getId()));
+ return Mono.just(itemResponse.getRequestCharge());
+ }) //Flux of request charges
+ .reduce(0.0,
+ (charge_n, charge_nplus1) -> charge_n + charge_nplus1
+ ) //Mono of total charge - there will be only one item in this stream
+ .subscribe(charge -> {
+ logger.info(String.format("Created items with total request charge of %.2f\n",
+ charge));
+ },
+ err -> {
+ if (err instanceof CosmosClientException) {
+ //Client-specific errors
+ CosmosClientException cerr = (CosmosClientException) err;
+ cerr.printStackTrace();
+ logger.info(String.format("Read Item failed with %s\n", cerr));
+ } else {
+ //General errors
+ err.printStackTrace();
+ }
+
+ completionLatch.countDown();
+ },
+ () -> {
+ completionLatch.countDown();
+ }
+ ); //Preserve the total charge and print aggregate charge/item count stats.
+
+ try {
+ completionLatch.await();
+ } catch (InterruptedException err) {
+ throw new AssertionError("Unexpected Interruption", err);
+ }
+
+ //
+ }
+
+ private void readItems(Flux familiesToCreate) {
+ // Using partition key for point read scenarios.
+ // This will help fast look up of items because of partition key
+ //
+
+ final CountDownLatch completionLatch = new CountDownLatch(1);
+
+ familiesToCreate.flatMap(family -> {
+ Mono> asyncItemResponseMono = container.readItem(family.getId(), new PartitionKey(family.getLastName()), Family.class);
+ return asyncItemResponseMono;
+ })
+ .subscribe(
+ itemResponse -> {
+ double requestCharge = itemResponse.getRequestCharge();
+ Duration requestLatency = itemResponse.getRequestLatency();
+ logger.info(String.format("Item successfully read with id %s with a charge of %.2f and within duration %s",
+ itemResponse.getItem().getId(), requestCharge, requestLatency));
+ },
+ err -> {
+ if (err instanceof CosmosClientException) {
+ //Client-specific errors
+ CosmosClientException cerr = (CosmosClientException) err;
+ cerr.printStackTrace();
+ logger.info(String.format("Read Item failed with %s\n", cerr));
+ } else {
+ //General errors
+ err.printStackTrace();
+ }
+
+ completionLatch.countDown();
+ },
+ () -> {
+ completionLatch.countDown();
+ }
+ );
+
+ try {
+ completionLatch.await();
+ } catch (InterruptedException err) {
+ throw new AssertionError("Unexpected Interruption", err);
+ }
+
+ //
+ }
+
+ private void queryItems() {
+ //
+ // Set some common query options
+
+ FeedOptions queryOptions = new FeedOptions();
+ queryOptions.setMaxItemCount(10);
+ // Set populate query metrics to get metrics around query executions
+ queryOptions.setPopulateQueryMetrics(true);
+
+ CosmosPagedFlux pagedFluxResponse = container.queryItems(
+ "SELECT * FROM Family WHERE Family.lastName IN ('Andersen', 'Wakefield', 'Johnson')", queryOptions, Family.class);
+
+ final CountDownLatch completionLatch = new CountDownLatch(1);
+
+ pagedFluxResponse.byPage().subscribe(
+ fluxResponse -> {
+ logger.info("Got a page of query result with " +
+ fluxResponse.getResults().size() + " items(s)"
+ + " and request charge of " + fluxResponse.getRequestCharge());
+
+ logger.info("Item Ids " + fluxResponse
+ .getResults()
+ .stream()
+ .map(Family::getId)
+ .collect(Collectors.toList()));
+ },
+ err -> {
+ if (err instanceof CosmosClientException) {
+ //Client-specific errors
+ CosmosClientException cerr = (CosmosClientException) err;
+ cerr.printStackTrace();
+ logger.error(String.format("Read Item failed with %s\n", cerr));
+ } else {
+ //General errors
+ err.printStackTrace();
+ }
+
+ completionLatch.countDown();
+ },
+ () -> {
+ completionLatch.countDown();
+ }
+ );
+
+ try {
+ completionLatch.await();
+ } catch (InterruptedException err) {
+ throw new AssertionError("Unexpected Interruption", err);
+ }
+
+ //
+ }
+
+ private void shutdown() {
+ try {
+ //Clean shutdown
+ logger.info("Deleting Cosmos DB resources");
+ logger.info("-Deleting container...");
+ if (container != null)
+ container.delete().subscribe();
+ logger.info("-Deleting database...");
+ if (database != null)
+ database.delete().subscribe();
+ logger.info("-Closing the client...");
+ } catch (Exception err) {
+ logger.error("Deleting Cosmos DB resources failed, will still attempt to close the client. See stack trace below.");
+ err.printStackTrace();
+ }
+ client.close();
+ logger.info("Done.");
+ }
+}
diff --git a/src/main/java/com/azure/cosmos/examples/indexmanagement/sync/SampleIndexManagement.java b/src/main/java/com/azure/cosmos/examples/indexmanagement/sync/SampleIndexManagement.java
new file mode 100644
index 0000000..748dbfe
--- /dev/null
+++ b/src/main/java/com/azure/cosmos/examples/indexmanagement/sync/SampleIndexManagement.java
@@ -0,0 +1,287 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.cosmos.examples.indexmanagement.sync;
+
+import com.azure.cosmos.ConnectionPolicy;
+import com.azure.cosmos.ConsistencyLevel;
+import com.azure.cosmos.CosmosClient;
+import com.azure.cosmos.CosmosClientBuilder;
+import com.azure.cosmos.CosmosClientException;
+import com.azure.cosmos.CosmosContainer;
+import com.azure.cosmos.CosmosDatabase;
+import com.azure.cosmos.CosmosPagedIterable;
+import com.azure.cosmos.examples.changefeed.SampleChangeFeedProcessor;
+import com.azure.cosmos.examples.common.AccountSettings;
+import com.azure.cosmos.examples.common.Families;
+import com.azure.cosmos.examples.common.Family;
+import com.azure.cosmos.models.CosmosContainerProperties;
+import com.azure.cosmos.models.CosmosItemRequestOptions;
+import com.azure.cosmos.models.CosmosItemResponse;
+import com.azure.cosmos.models.ExcludedPath;
+import com.azure.cosmos.models.FeedOptions;
+import com.azure.cosmos.models.IncludedPath;
+import com.azure.cosmos.models.IndexingMode;
+import com.azure.cosmos.models.IndexingPolicy;
+import com.azure.cosmos.models.PartitionKey;
+import com.google.common.collect.Lists;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class SampleIndexManagement {
+
+ private CosmosClient client;
+
+ private final String databaseName = "AzureSampleFamilyDB";
+ private final String containerName = "FamilyContainer";
+
+ private CosmosDatabase database;
+ private CosmosContainer container;
+
+ protected static Logger logger = LoggerFactory.getLogger(SampleChangeFeedProcessor.class.getSimpleName());
+
+ public void close() {
+ client.close();
+ }
+
+ /**
+ * Run a Hello CosmosDB console application.
+ *
+ * This sample is similar to SampleCRUDQuickstart, but modified to show indexing capabilities of Cosmos DB.
+ * Look at the implementation of createContainerIfNotExistsWithSpecifiedIndex() for the demonstration of
+ * indexing capabilities.
+ */
+ //
+ public static void main(String[] args) {
+
+ SampleIndexManagement p = new SampleIndexManagement();
+
+ try {
+ logger.info("Starting SYNC main");
+ p.indexManagementDemo();
+ logger.info("Demo complete, please hold while resources are released");
+ } catch (Exception e) {
+ e.printStackTrace();
+ logger.error(String.format("Cosmos getStarted failed with %s", e));
+ } finally {
+ logger.info("Closing the client");
+ p.shutdown();
+ }
+ }
+
+ //
+
+ private void indexManagementDemo() throws Exception {
+
+ logger.info("Using Azure Cosmos DB endpoint: " + AccountSettings.HOST);
+
+ ConnectionPolicy defaultPolicy = ConnectionPolicy.getDefaultPolicy();
+ // Setting the preferred location to Cosmos DB Account region
+ // West US is just an example. User should set preferred location to the Cosmos DB region closest to the application
+ defaultPolicy.setPreferredLocations(Lists.newArrayList("West US"));
+
+ // Create sync client
+ //
+ client = new CosmosClientBuilder()
+ .setEndpoint(AccountSettings.HOST)
+ .setKey(AccountSettings.MASTER_KEY)
+ .setConnectionPolicy(defaultPolicy)
+ .setConsistencyLevel(ConsistencyLevel.EVENTUAL)
+ .buildClient();
+
+ //
+
+ createDatabaseIfNotExists();
+
+ //Here is where index management is performed
+ createContainerIfNotExistsWithSpecifiedIndex();
+
+ // Setup family items to create
+ ArrayList familiesToCreate = new ArrayList<>();
+ familiesToCreate.add(Families.getAndersenFamilyItem());
+ familiesToCreate.add(Families.getWakefieldFamilyItem());
+ familiesToCreate.add(Families.getJohnsonFamilyItem());
+ familiesToCreate.add(Families.getSmithFamilyItem());
+
+ createFamilies(familiesToCreate);
+
+ logger.info("Reading items.");
+ readItems(familiesToCreate);
+
+ logger.info("Querying items.");
+ queryItems();
+ }
+
+ private void createDatabaseIfNotExists() throws Exception {
+ logger.info("Create database " + databaseName + " if not exists.");
+
+ // Create database if not exists
+ //
+ database = client.createDatabaseIfNotExists(databaseName).getDatabase();
+ //
+
+ logger.info("Checking database " + database.getId() + " completed!\n");
+ }
+
+ private void createContainerIfNotExistsWithSpecifiedIndex() throws Exception {
+ logger.info("Create container " + containerName + " if not exists.");
+
+ // Create container if not exists
+ CosmosContainerProperties containerProperties =
+ new CosmosContainerProperties(containerName, "/lastName");
+
+ //
+ IndexingPolicy indexingPolicy = new IndexingPolicy();
+ indexingPolicy.setIndexingMode(IndexingMode.CONSISTENT); //To turn indexing off set IndexingMode.NONE
+
+ // Included paths
+ List includedPaths = new ArrayList<>();
+ IncludedPath includedPath = new IncludedPath();
+ includedPath.setPath("/*");
+ includedPaths.add(includedPath);
+ indexingPolicy.setIncludedPaths(includedPaths);
+
+ // Excluded paths
+ List excludedPaths = new ArrayList<>();
+ ExcludedPath excludedPath = new ExcludedPath();
+ excludedPath.setPath("/name/*");
+ excludedPaths.add(excludedPath);
+ indexingPolicy.setExcludedPaths(excludedPaths);
+
+ // Spatial indices - if you need them, here is how to set them up:
+ /*
+ List spatialIndexes = new ArrayList();
+ List collectionOfSpatialTypes = new ArrayList();
+
+ SpatialSpec spec = new SpatialSpec();
+ spec.setPath("/locations/*");
+ collectionOfSpatialTypes.add(SpatialType.Point);
+ spec.setSpatialTypes(collectionOfSpatialTypes);
+ spatialIndexes.add(spec);
+
+ indexingPolicy.setSpatialIndexes(spatialIndexes);
+ */
+
+ // Composite indices - if you need them, here is how to set them up:
+ /*
+ List> compositeIndexes = new ArrayList<>();
+ List compositePaths = new ArrayList<>();
+
+ CompositePath nameCompositePath = new CompositePath();
+ nameCompositePath.setPath("/name");
+ nameCompositePath.setOrder(CompositePathSortOrder.ASCENDING);
+
+ CompositePath ageCompositePath = new CompositePath();
+ ageCompositePath.setPath("/age");
+ ageCompositePath.setOrder(CompositePathSortOrder.DESCENDING);
+
+ compositePaths.add(ageCompositePath);
+ compositePaths.add(nameCompositePath);
+
+ compositeIndexes.add(compositePaths);
+ indexingPolicy.setCompositeIndexes(compositeIndexes);
+ */
+
+ containerProperties.setIndexingPolicy(indexingPolicy);
+
+ //
+
+ // Create container with 400 RU/s
+ container = database.createContainerIfNotExists(containerProperties, 400).getContainer();
+
+ logger.info("Checking container " + container.getId() + " completed!\n");
+ }
+
+ private void createFamilies(List families) throws Exception {
+ double totalRequestCharge = 0;
+ for (Family family : families) {
+
+ //
+ // Create item using container that we created using sync client
+
+ // Use lastName as partitionKey for cosmos item
+ // Using appropriate partition key improves the performance of database operations
+ CosmosItemRequestOptions cosmosItemRequestOptions = new CosmosItemRequestOptions();
+ CosmosItemResponse item = container.createItem(family, new PartitionKey(family.getLastName()), cosmosItemRequestOptions);
+ //
+
+ // Get request charge and other properties like latency, and diagnostics strings, etc.
+ logger.info(String.format("Created item with request charge of %.2f within" +
+ " duration %s",
+ item.getRequestCharge(), item.getRequestLatency()));
+ totalRequestCharge += item.getRequestCharge();
+ }
+ logger.info(String.format("Created %d items with total request " +
+ "charge of %.2f",
+ families.size(),
+ totalRequestCharge));
+ }
+
+ private void readItems(ArrayList familiesToCreate) {
+ // Using partition key for point read scenarios.
+ // This will help fast look up of items because of partition key
+ familiesToCreate.forEach(family -> {
+ //
+ try {
+ CosmosItemResponse item = container.readItem(family.getId(), new PartitionKey(family.getLastName()), Family.class);
+ double requestCharge = item.getRequestCharge();
+ Duration requestLatency = item.getRequestLatency();
+ logger.info(String.format("Item successfully read with id %s with a charge of %.2f and within duration %s",
+ item.getResource().getId(), requestCharge, requestLatency));
+ } catch (CosmosClientException e) {
+ e.printStackTrace();
+ logger.error(String.format("Read Item failed with %s", e));
+ }
+ //
+ });
+ }
+
+ private void queryItems() {
+ //
+ // Set some common query options
+ FeedOptions queryOptions = new FeedOptions();
+ queryOptions.setMaxItemCount(10);
+ // Set populate query metrics to get metrics around query executions
+ queryOptions.setPopulateQueryMetrics(true);
+
+ CosmosPagedIterable familiesPagedIterable = container.queryItems(
+ "SELECT * FROM Family WHERE Family.lastName IN ('Andersen', 'Wakefield', 'Johnson')", queryOptions, Family.class);
+
+ familiesPagedIterable.iterableByPage().forEach(cosmosItemPropertiesFeedResponse -> {
+ logger.info("Got a page of query result with " +
+ cosmosItemPropertiesFeedResponse.getResults().size() + " items(s)"
+ + " and request charge of " + cosmosItemPropertiesFeedResponse.getRequestCharge());
+
+ logger.info("Item Ids " + cosmosItemPropertiesFeedResponse
+ .getResults()
+ .stream()
+ .map(Family::getId)
+ .collect(Collectors.toList()));
+ });
+ //
+ }
+
+ private void shutdown() {
+ try {
+ //Clean shutdown
+ logger.info("Deleting Cosmos DB resources");
+ logger.info("-Deleting container...");
+ if (container != null)
+ container.delete();
+ logger.info("-Deleting database...");
+ if (database != null)
+ database.delete();
+ logger.info("-Closing the client...");
+ } catch (Exception err) {
+ logger.error("Deleting Cosmos DB resources failed, will still attempt to close the client. See stack trace below.");
+ err.printStackTrace();
+ }
+ client.close();
+ logger.info("Done.");
+ }
+}
diff --git a/src/main/java/com/azure/cosmos/examples/storedprocedure/async/SampleStoredProcedureAsync.java b/src/main/java/com/azure/cosmos/examples/storedprocedure/async/SampleStoredProcedureAsync.java
new file mode 100644
index 0000000..21ca683
--- /dev/null
+++ b/src/main/java/com/azure/cosmos/examples/storedprocedure/async/SampleStoredProcedureAsync.java
@@ -0,0 +1,222 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.cosmos.examples.storedprocedure.async;
+
+import com.azure.cosmos.ConnectionPolicy;
+import com.azure.cosmos.ConsistencyLevel;
+import com.azure.cosmos.CosmosAsyncClient;
+import com.azure.cosmos.CosmosAsyncContainer;
+import com.azure.cosmos.CosmosAsyncDatabase;
+import com.azure.cosmos.CosmosClientBuilder;
+import com.azure.cosmos.CosmosClientException;
+import com.azure.cosmos.CosmosPagedFlux;
+import com.azure.cosmos.examples.changefeed.SampleChangeFeedProcessor;
+import com.azure.cosmos.examples.common.AccountSettings;
+import com.azure.cosmos.examples.common.CustomPOJO;
+import com.azure.cosmos.models.CosmosAsyncItemResponse;
+import com.azure.cosmos.models.CosmosContainerProperties;
+import com.azure.cosmos.models.CosmosStoredProcedureProperties;
+import com.azure.cosmos.models.CosmosStoredProcedureRequestOptions;
+import com.azure.cosmos.models.FeedOptions;
+import com.azure.cosmos.models.PartitionKey;
+import com.google.common.collect.Lists;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import reactor.core.publisher.Mono;
+
+import java.util.concurrent.CountDownLatch;
+
+public class SampleStoredProcedureAsync {
+
+ private CosmosAsyncClient client;
+
+ private final String databaseName = "SprocTestDB";
+ private final String containerName = "SprocTestContainer";
+
+ private CosmosAsyncDatabase database;
+ private CosmosAsyncContainer container;
+
+ private String sprocId;
+
+ protected static Logger logger = LoggerFactory.getLogger(SampleChangeFeedProcessor.class.getSimpleName());
+
+ public void close() {
+ client.close();
+ }
+
+ /**
+ * Stored Procedure Example
+ *
+ * This sample code demonstrates creation, execution, and effects of stored procedures
+ * using Java SDK. A stored procedure is created which will insert a JSON object into
+ * a Cosmos DB container. The sample executes the stored procedure and then performs
+ * a point-read to confirm that the stored procedure had the intended effect.
+ */
+ //
+ public static void main(String[] args) {
+ SampleStoredProcedureAsync p = new SampleStoredProcedureAsync();
+
+ try {
+ p.sprocDemo();
+ logger.info("Demo complete, please hold while resources are released");
+ p.shutdown();
+ logger.info("Done.\n");
+ } catch (Exception e) {
+ e.printStackTrace();
+ logger.info(String.format("Cosmos getStarted failed with %s", e));
+ p.close();
+ } finally {
+ }
+ }
+
+ //
+
+ private void sprocDemo() throws Exception {
+ //Setup client, DB, and the container for which we will create stored procedures
+ //The container partition key will be id
+ setUp();
+
+ //Create stored procedure and list all stored procedures that have been created.
+ createStoredProcedure();
+ readAllSprocs();
+
+ //Execute the stored procedure, which we expect will create an item with id test_doc
+ executeStoredProcedure();
+
+ //Perform a point-read to confirm that the item with id test_doc exists
+ logger.info("Checking that a document was created by the stored procedure...");
+ CosmosAsyncItemResponse test_resp =
+ container.readItem("test_doc", new PartitionKey("test_doc"), CustomPOJO.class).block();
+ logger.info(String.format(
+ "Status return value of point-read for document created by stored procedure (200 indicates success): %d", test_resp.getStatusCode()));
+ }
+
+ public void setUp() throws Exception {
+ logger.info("Using Azure Cosmos DB endpoint: " + AccountSettings.HOST);
+
+ ConnectionPolicy defaultPolicy = ConnectionPolicy.getDefaultPolicy();
+ // Setting the preferred location to Cosmos DB Account region
+ // West US is just an example. User should set preferred location to the Cosmos DB region closest to the application
+ defaultPolicy.setPreferredLocations(Lists.newArrayList("West US"));
+
+ // Create sync client
+ //
+ client = new CosmosClientBuilder()
+ .setEndpoint(AccountSettings.HOST)
+ .setKey(AccountSettings.MASTER_KEY)
+ .setConnectionPolicy(defaultPolicy)
+ .setConsistencyLevel(ConsistencyLevel.EVENTUAL)
+ .buildAsyncClient();
+
+ logger.info("Create database " + databaseName + " with container " + containerName + " if either does not already exist.\n");
+
+ client.createDatabaseIfNotExists(databaseName).flatMap(databaseResponse -> {
+ database = databaseResponse.getDatabase();
+ return Mono.empty();
+ }).block();
+
+ CosmosContainerProperties containerProperties =
+ new CosmosContainerProperties(containerName, "/id");
+ database.createContainerIfNotExists(containerProperties, 400).flatMap(containerResponse -> {
+ container = containerResponse.getContainer();
+ return Mono.empty();
+ }).block();
+ }
+
+ public void shutdown() throws Exception {
+ //Safe clean & close
+ deleteStoredProcedure();
+ }
+
+ public void createStoredProcedure() throws Exception {
+ logger.info("Creating stored procedure...\n");
+
+ sprocId = "createMyDocument";
+ String sprocBody = "function createMyDocument() {\n" +
+ "var documentToCreate = {\"id\":\"test_doc\"}\n" +
+ "var context = getContext();\n" +
+ "var collection = context.getCollection();\n" +
+ "var accepted = collection.createDocument(collection.getSelfLink(), documentToCreate,\n" +
+ " function (err, documentCreated) {\n" +
+ "if (err) throw new Error('Error' + err.message);\n" +
+ "context.getResponse().setBody(documentCreated.id)\n" +
+ "});\n" +
+ "if (!accepted) return;\n" +
+ "}";
+ CosmosStoredProcedureProperties storedProcedureDef = new CosmosStoredProcedureProperties(sprocId, sprocBody);
+ container.getScripts()
+ .createStoredProcedure(storedProcedureDef,
+ new CosmosStoredProcedureRequestOptions()).block();
+ }
+
+ private void readAllSprocs() throws Exception {
+
+ FeedOptions feedOptions = new FeedOptions();
+ CosmosPagedFlux fluxResponse =
+ container.getScripts().readAllStoredProcedures(feedOptions);
+
+ final CountDownLatch completionLatch = new CountDownLatch(1);
+
+
+ fluxResponse.flatMap(storedProcedureProperties -> {
+ logger.info(String.format("Stored Procedure: %s\n", storedProcedureProperties.getId()));
+ return Mono.empty();
+ }).subscribe(
+ s -> {
+ },
+ err -> {
+ if (err instanceof CosmosClientException) {
+ //Client-specific errors
+ CosmosClientException cerr = (CosmosClientException) err;
+ cerr.printStackTrace();
+ logger.info(String.format("Read Item failed with %s\n", cerr));
+ } else {
+ //General errors
+ err.printStackTrace();
+ }
+
+ completionLatch.countDown();
+ },
+ () -> {
+ completionLatch.countDown();
+ }
+ );
+
+ completionLatch.await();
+ }
+
+ public void executeStoredProcedure() throws Exception {
+ logger.info(String.format("Executing stored procedure %s...\n\n", sprocId));
+
+ CosmosStoredProcedureRequestOptions options = new CosmosStoredProcedureRequestOptions();
+ options.setPartitionKey(new PartitionKey("test_doc"));
+
+ container.getScripts()
+ .getStoredProcedure(sprocId)
+ .execute(null, options)
+ .flatMap(executeResponse -> {
+ logger.info(String.format("Stored procedure %s returned %s (HTTP %d), at cost %.3f RU.\n",
+ sprocId,
+ executeResponse.getResponseAsString(),
+ executeResponse.getStatusCode(),
+ executeResponse.getRequestCharge()));
+ return Mono.empty();
+ }).block();
+ }
+
+ public void deleteStoredProcedure() throws Exception {
+ logger.info("-Deleting stored procedure...\n");
+ container.getScripts()
+ .getStoredProcedure(sprocId)
+ .delete().block();
+ logger.info("-Deleting database...\n");
+ database.delete().block();
+ logger.info("-Closing client instance...\n");
+ client.close();
+ }
+}
diff --git a/src/main/java/com/azure/cosmos/examples/storedprocedure/sync/SampleStoredProcedure.java b/src/main/java/com/azure/cosmos/examples/storedprocedure/sync/SampleStoredProcedure.java
new file mode 100644
index 0000000..2061c5a
--- /dev/null
+++ b/src/main/java/com/azure/cosmos/examples/storedprocedure/sync/SampleStoredProcedure.java
@@ -0,0 +1,187 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.cosmos.examples.storedprocedure.sync;
+
+import com.azure.cosmos.ConnectionPolicy;
+import com.azure.cosmos.ConsistencyLevel;
+import com.azure.cosmos.CosmosClient;
+import com.azure.cosmos.CosmosClientBuilder;
+import com.azure.cosmos.CosmosContainer;
+import com.azure.cosmos.CosmosDatabase;
+import com.azure.cosmos.CosmosPagedIterable;
+import com.azure.cosmos.examples.changefeed.SampleChangeFeedProcessor;
+import com.azure.cosmos.examples.common.AccountSettings;
+import com.azure.cosmos.examples.common.CustomPOJO;
+import com.azure.cosmos.models.CosmosContainerProperties;
+import com.azure.cosmos.models.CosmosItemResponse;
+import com.azure.cosmos.models.CosmosStoredProcedureProperties;
+import com.azure.cosmos.models.CosmosStoredProcedureRequestOptions;
+import com.azure.cosmos.models.CosmosStoredProcedureResponse;
+import com.azure.cosmos.models.FeedOptions;
+import com.azure.cosmos.models.PartitionKey;
+import com.google.common.collect.Lists;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Iterator;
+
+public class SampleStoredProcedure {
+
+ private CosmosClient client;
+
+ private final String databaseName = "SprocTestDB";
+ private final String containerName = "SprocTestContainer";
+
+ private CosmosDatabase database;
+ private CosmosContainer container;
+
+ private String sprocId;
+
+ protected static Logger logger = LoggerFactory.getLogger(SampleChangeFeedProcessor.class.getSimpleName());
+
+ public void close() {
+ client.close();
+ }
+
+ /**
+ * Stored Procedure Example
+ *
+ * This sample code demonstrates creation, execution, and effects of stored procedures
+ * using Java SDK. A stored procedure is created which will insert a JSON object into
+ * a Cosmos DB container. The sample executes the stored procedure and then performs
+ * a point-read to confirm that the stored procedure had the intended effect.
+ */
+ //
+ public static void main(String[] args) {
+ SampleStoredProcedure p = new SampleStoredProcedure();
+
+ try {
+ p.sprocDemo();
+ logger.info("Demo complete, please hold while resources are released");
+ p.shutdown();
+ logger.info("Done.\n");
+ } catch (Exception e) {
+ e.printStackTrace();
+ logger.error(String.format("Cosmos getStarted failed with %s", e));
+ p.close();
+ } finally {
+ }
+ }
+
+ //
+
+ private void sprocDemo() throws Exception {
+ //Setup client, DB, and the container for which we will create stored procedures
+ //The container partition key will be id
+ setUp();
+
+ //Create stored procedure and list all stored procedures that have been created.
+ createStoredProcedure();
+ readAllSprocs();
+
+ //Execute the stored procedure, which we expect will create an item with id test_doc
+ executeStoredProcedure();
+
+ //Perform a point-read to confirm that the item with id test_doc exists
+ logger.info("Checking that a document was created by the stored procedure...");
+ CosmosItemResponse test_resp = container.readItem("test_doc", new PartitionKey("test_doc"), CustomPOJO.class);
+ logger.info(String.format(
+ "Result of point-read for document created by stored procedure (200 indicates success): %d", test_resp.getStatusCode()));
+ }
+
+ public void setUp() throws Exception {
+ logger.info("Using Azure Cosmos DB endpoint: " + AccountSettings.HOST);
+
+ ConnectionPolicy defaultPolicy = ConnectionPolicy.getDefaultPolicy();
+ // Setting the preferred location to Cosmos DB Account region
+ // West US is just an example. User should set preferred location to the Cosmos DB region closest to the application
+ defaultPolicy.setPreferredLocations(Lists.newArrayList("West US"));
+
+ // Create sync client
+ //
+ client = new CosmosClientBuilder()
+ .setEndpoint(AccountSettings.HOST)
+ .setKey(AccountSettings.MASTER_KEY)
+ .setConnectionPolicy(defaultPolicy)
+ .setConsistencyLevel(ConsistencyLevel.EVENTUAL)
+ .buildClient();
+
+ logger.info("Create database " + databaseName + " with container " + containerName + " if either does not already exist.\n");
+
+ database = client.createDatabaseIfNotExists(databaseName).getDatabase();
+
+ CosmosContainerProperties containerProperties =
+ new CosmosContainerProperties(containerName, "/id");
+ container = database.createContainerIfNotExists(containerProperties, 400).getContainer();
+ }
+
+ public void shutdown() throws Exception {
+ //Safe clean & close
+ deleteStoredProcedure();
+ }
+
+ public void createStoredProcedure() throws Exception {
+ logger.info("Creating stored procedure...");
+
+ sprocId = "createMyDocument";
+ String sprocBody = "function createMyDocument() {\n" +
+ "var documentToCreate = {\"id\":\"test_doc\"}\n" +
+ "var context = getContext();\n" +
+ "var collection = context.getCollection();\n" +
+ "var accepted = collection.createDocument(collection.getSelfLink(), documentToCreate,\n" +
+ " function (err, documentCreated) {\n" +
+ "if (err) throw new Error('Error' + err.message);\n" +
+ "context.getResponse().setBody(documentCreated.id)\n" +
+ "});\n" +
+ "if (!accepted) return;\n" +
+ "}";
+ CosmosStoredProcedureProperties storedProcedureDef = new CosmosStoredProcedureProperties(sprocId, sprocBody);
+ container.getScripts()
+ .createStoredProcedure(storedProcedureDef,
+ new CosmosStoredProcedureRequestOptions());
+ }
+
+ private void readAllSprocs() throws Exception {
+ logger.info("Listing all stored procedures associated with container " + containerName + "\n");
+
+ FeedOptions feedOptions = new FeedOptions();
+ CosmosPagedIterable feedResponseIterable =
+ container.getScripts().readAllStoredProcedures(feedOptions);
+
+ Iterator feedResponseIterator = feedResponseIterable.iterator();
+
+ while (feedResponseIterator.hasNext()) {
+ CosmosStoredProcedureProperties storedProcedureProperties = feedResponseIterator.next();
+ logger.info(String.format("Stored Procedure: %s", storedProcedureProperties));
+ }
+ }
+
+ public void executeStoredProcedure() throws Exception {
+ logger.info(String.format("Executing stored procedure %s...\n\n", sprocId));
+
+ CosmosStoredProcedureRequestOptions options = new CosmosStoredProcedureRequestOptions();
+ options.setPartitionKey(new PartitionKey("test_doc"));
+ CosmosStoredProcedureResponse executeResponse = container.getScripts()
+ .getStoredProcedure(sprocId)
+ .execute(null, options);
+
+ logger.info(String.format("Stored procedure %s returned %s (HTTP %d), at cost %.3f RU.\n",
+ sprocId,
+ executeResponse.responseAsString(),
+ executeResponse.getStatusCode(),
+ executeResponse.getRequestCharge()));
+ }
+
+ public void deleteStoredProcedure() throws Exception {
+ logger.info("-Deleting stored procedure...\n");
+ container.getScripts()
+ .getStoredProcedure(sprocId)
+ .delete();
+ logger.info("-Deleting database...\n");
+ database.delete();
+ logger.info("-Closing client instance...\n");
+ client.close();
+ logger.info("Done.");
+ }
+}
diff --git a/src/main/resources/log4j2.properties b/src/main/resources/log4j2.properties
new file mode 100644
index 0000000..f1178ab
--- /dev/null
+++ b/src/main/resources/log4j2.properties
@@ -0,0 +1,14 @@
+# this is the log4j configuration for tests
+# Set root logger level to WARN and its appender to STDOUT.
+rootLogger.level=INFO
+rootLogger.appenderRef.stdout.ref=STDOUT
+logger.netty.name=io.netty
+logger.netty.level=INFO
+logger.cosmos.name=com.azure.cosmos
+logger.cosmos.level=INFO
+# STDOUT is a ConsoleAppender and uses PatternLayout.
+appender.console.name=STDOUT
+appender.console.type=Console
+appender.console.layout.type=PatternLayout
+appender.console.layout.pattern=%m%n
+
diff --git a/src/main/resources/multi-master-sample-config.properties b/src/main/resources/multi-master-sample-config.properties
new file mode 100644
index 0000000..42c2030
--- /dev/null
+++ b/src/main/resources/multi-master-sample-config.properties
@@ -0,0 +1,8 @@
+endpoint=
+key=
+regions=North Central US;North Europe;Southeast Asia
+databaseName=multiMasterDemoDB
+manualCollectionName=myManualCollection
+lwwCollectionName=myLwwCollection
+udpCollectionName=myUdpCollection
+basicCollectionName=myBasicCollection
\ No newline at end of file
diff --git a/src/main/resources/resolver-storedproc.txt b/src/main/resources/resolver-storedproc.txt
new file mode 100644
index 0000000..e856721
--- /dev/null
+++ b/src/main/resources/resolver-storedproc.txt
@@ -0,0 +1,45 @@
+function resolver(incomingRecord, existingRecord, isTombstone, conflictingRecords) {
+ var collection = getContext().getCollection();
+ if (!incomingRecord) {
+ if (existingRecord) {
+ collection.deleteDocument(existingRecord._self, {}, function(err, responseOptions) {
+ if (err) throw err;
+ });
+ }
+ } else if (isTombstone) {
+ // delete always wins.
+ } else {
+ var documentToUse = incomingRecord;
+ if (existingRecord) {
+ if (documentToUse.regionId < existingRecord.regionId) {
+ documentToUse = existingRecord;
+ }
+ }
+ var i;
+ for (i = 0; i < conflictingRecords.length; i++) {
+ if (documentToUse.regionId < conflictingRecords[i].regionId) {
+ documentToUse = conflictingRecords[i];
+ }
+ }
+ tryDelete(conflictingRecords, incomingRecord, existingRecord, documentToUse);
+ }
+ function tryDelete(documents, incoming, existing, documentToInsert) {
+ if (documents.length > 0) {
+ collection.deleteDocument(documents[0]._self, {}, function(err, responseOptions) {
+ if (err) throw err;
+ documents.shift();
+ tryDelete(documents, incoming, existing, documentToInsert);
+ });
+ } else if (existing) {
+ collection.replaceDocument(existing._self, documentToInsert,
+ function(err, documentCreated) {
+ if (err) throw err;
+ });
+ } else {
+ collection.createDocument(collection.getSelfLink(), documentToInsert,
+ function(err, documentCreated) {
+ if (err) throw err;
+ });
+ }
+ }
+}
\ No newline at end of file