├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── SECURITY.md ├── SUPPORT.md ├── data ├── ProductsWithManufacturers.csv ├── SampleRelationalData.xlsx ├── TransformExcel.ipynb └── products.json ├── demos ├── .gitignore ├── cosmos-db │ ├── debugging │ │ └── Cosmosdb.postman_collection.json │ └── demo │ │ ├── .mvn │ │ └── wrapper │ │ │ └── maven-wrapper.properties │ │ ├── README.md │ │ ├── mvnw │ │ ├── mvnw.cmd │ │ ├── pom.xml │ │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── demo │ │ │ │ ├── DemoApplication.java │ │ │ │ ├── config │ │ │ │ └── CosmosConfiguration.java │ │ │ │ ├── controller │ │ │ │ ├── BulkController.java │ │ │ │ ├── ChangeFeedController.java │ │ │ │ ├── CustomerController.java │ │ │ │ ├── ManufacturerController.java │ │ │ │ ├── ProductController.java │ │ │ │ └── WishlistController.java │ │ │ │ ├── dao │ │ │ │ ├── CustomerRepository.java │ │ │ │ ├── ManufacturerRepository.java │ │ │ │ ├── ProductRepository.java │ │ │ │ └── WishlistRepository.java │ │ │ │ ├── model │ │ │ │ ├── BaseModel.java │ │ │ │ ├── Customer.java │ │ │ │ ├── Manufacturer.java │ │ │ │ ├── Product.java │ │ │ │ └── Wishlist.java │ │ │ │ └── service │ │ │ │ ├── BulkExecutorService.java │ │ │ │ ├── ChangeFeedService.java │ │ │ │ ├── ChangedProductSink.java │ │ │ │ ├── CustomerService.java │ │ │ │ ├── ManufacturerService.java │ │ │ │ ├── ProductService.java │ │ │ │ └── WishlistService.java │ │ └── resources │ │ │ ├── application-default.properties │ │ │ ├── application.properties │ │ │ └── static │ │ │ ├── Cosmosdb.postman_collection.json │ │ │ └── index.html │ │ └── test │ │ └── java │ │ └── com │ │ └── example │ │ └── demo │ │ └── DemoApplicationTests.java ├── cosmos-function │ └── azure-cosmos-db-function-demo-from-maven │ │ └── function │ │ ├── host.json │ │ ├── pom.xml │ │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── Function.java ├── hello-world-keyvault │ └── demo │ │ ├── .mvn │ │ └── wrapper │ │ │ ├── MavenWrapperDownloader.java │ │ │ └── maven-wrapper.properties │ │ ├── mvnw │ │ ├── mvnw.cmd │ │ ├── pom.xml │ │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── demo │ │ │ │ ├── DemoApplication.java │ │ │ │ └── KeyvaultDemoController.java │ │ └── resources │ │ │ └── application.properties │ │ └── test │ │ └── java │ │ └── com │ │ └── example │ │ └── demo │ │ └── DemoApplicationTests.java └── host.json └── docs ├── .gitignore ├── _config.yml ├── _includes ├── footer.html ├── links.html └── navigation.html ├── _layouts ├── default.html ├── home.html └── page.html ├── _sass ├── code.scss ├── cosmos.scss ├── fonts.scss └── theme.scss ├── assets ├── css │ └── style.scss └── img │ ├── logo.png │ └── logo.svg ├── bulk-executor.md ├── change-feed-concepts.md ├── change-feed-with-cosmos-db-trigger-function.md ├── crud-operations-with-cosmos-db.md ├── deploy-to-azure-app-service.md ├── event-sourcing.md ├── foreword.md ├── get-started-with-java-and-cosmos-db.md ├── get-started-with-java-and-key-vault.md ├── index.md ├── intro-cosmos.md ├── intro-nosql.md ├── media ├── change-feed-concepts │ └── change-feed-processor.png ├── change-feed-with-cosmos-db-trigger-function │ ├── function-app-configuration.png │ └── function-app-monitor.png ├── deploy-to-azure-app-service │ └── app-service-configuration.png ├── event-sourcing │ ├── cosmos-db-trigger.png │ ├── event-hubs-instance-overview.png │ └── function-app-configuration.png ├── get-started-with-java-and-key-vault │ ├── key-vault-access-policies.png │ ├── select-key-current-version.png │ ├── select-key-vault-app-application-settings.png │ ├── select-key-vault-app.png │ ├── select-key-vault.png │ ├── select-resource-groups.png │ ├── select-show-secret-value.png │ ├── spring-initializr-install.png │ ├── view-key-vault-app-url.png │ └── view-secret-value.png ├── index │ ├── cover.ai │ └── cover.svg ├── intro-cosmos │ └── consistency_scale.svg ├── intro-nosql │ └── relational_tables.svg ├── migrate-to-azure-spring-apps │ ├── azure-spring-apps-config-server.png │ ├── azure-spring-apps-deployment.png │ ├── config-server-settings.png │ ├── create-service-binding-page-settings.png │ ├── select-add-diagnostic-setting.png │ ├── select-create-service-binding.png │ └── view-service-binding-page.png ├── mission-critical-situations-for-cosmos-db │ ├── backup-and-restore-settings.png │ └── firewall-and-virtual-network-settings.png ├── scaling-in-cosmos-db │ ├── manual-scale-settings.png │ └── provision-throughput-selected.png ├── schema-considerations │ ├── contoso-pet-supplies-partitions.png │ └── contoso-pet-supplies-relational-database-model.png └── send-notifications-with-azure-logic-apps │ ├── search-for-event-hub.png │ ├── search-for-logic-app.png │ ├── select-blank-logic-app.png │ └── select-create-resource.png ├── migrate-to-azure-spring-apps.md ├── mission-critical-situations-for-cosmos-db.md ├── scaling-in-cosmos-db.md ├── schema-considerations.md ├── security.md └── send-notifications-with-azure-logic-apps.md /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Microsoft Open Source Code of Conduct 2 | 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 4 | 5 | Resources: 6 | 7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) 8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cloud-Scale Data for Spring Developers 2 | 3 | > Java + Azure Cosmos DB + Azure Spring Apps + Azure Functions + Azure Cognitive Search + more! 4 | 5 | ![Screenshot of book cover featuring title, an illustration of developer tools, the Azure Cosmos DB logo, a subtitle, and a version moniker. In this screenshot, the title is "Cloud-Scale Data for Spring Developers", the subtitle is "Bring cloud-native Java applications to Azure using Azure Cosmos DB SQL API", and the version is "1.0".](docs/media/index/cover.svg) 6 | 7 | [Get started reading the guide!](docs/index.md) 8 | 9 | ## Contributing 10 | 11 | This project welcomes contributions and suggestions. Most contributions require you to agree to a 12 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us 13 | the rights to use your contribution. For details, visit . 14 | 15 | When you submit a pull request, a CLA bot will automatically determine whether you need to provide 16 | a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions 17 | provided by the bot. You will only need to do this once across all repos using our CLA. 18 | 19 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 20 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or 21 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 22 | 23 | ## Trademarks 24 | 25 | This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow [Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general). 26 | Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. 27 | Any use of third-party trademarks or logos are subject to those third-party's policies. -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Security 4 | 5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). 6 | 7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. 8 | 9 | ## Reporting Security Issues 10 | 11 | **Please do not report security vulnerabilities through public GitHub issues.** 12 | 13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). 14 | 15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). 16 | 17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). 18 | 19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 20 | 21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 22 | * Full paths of source file(s) related to the manifestation of the issue 23 | * The location of the affected source code (tag/branch/commit or direct URL) 24 | * Any special configuration required to reproduce the issue 25 | * Step-by-step instructions to reproduce the issue 26 | * Proof-of-concept or exploit code (if possible) 27 | * Impact of the issue, including how an attacker might exploit the issue 28 | 29 | This information will help us triage your report more quickly. 30 | 31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. 32 | 33 | ## Preferred Languages 34 | 35 | We prefer all communications to be in English. 36 | 37 | ## Policy 38 | 39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). 40 | 41 | 42 | -------------------------------------------------------------------------------- /SUPPORT.md: -------------------------------------------------------------------------------- 1 | # Support 2 | 3 | ## How to file issues and get help 4 | 5 | This project uses GitHub Issues to track bugs and feature requests. Please search the existing issues before filing new issues to avoid duplicates. For new issues, file your bug or feature request as a new Issue. 6 | 7 | For help and questions about using this project, please file a bug using GitHub issues. 8 | 9 | ## Microsoft Support Policy 10 | 11 | Support for this **PROJECT or PRODUCT** is limited to the resources listed above. 12 | -------------------------------------------------------------------------------- /data/ProductsWithManufacturers.csv: -------------------------------------------------------------------------------- 1 | ProductId,Name,Description,MSRP,Manufacturer 2 | 1,Fetching Collection,"A collection of balls, sticks, and other toys for playing fetch",29.99,HulaHula 3 | 2,Pecan Rounded Corner Perch,Rounded corner perch to be mounted in a cage for small pets. Includes mounting parts.,9.99,Parts Unlimited 4 | 3,Rectangle Perch,Pine perch used for small pets. Mounting hardware included.,12.99,Parts Unlimited 5 | 4,"Pet Playpen, Large","When you want to let your pets play but want them confined to an area. Good for medium and large dogs, cats, and capybaras.",59.99,Northwind Traders 6 | 5,"Pet Playpen, Medium",When you want to let your pets play but want them confined to an area. Good for small to medium dogs and cats.,39.99,Northwind Traders 7 | 6,"Pet Playpen, Small","When you want to let your pets play but want them confined to an area. Good for small pets - such as chinchillas, guinea pigs, and hamsters.",19.99,Northwind Traders 8 | 7,"Pet First Aid Kit, Horse","Kit includes: hoof care kit, wound care, bandages, tweezers, thermometer, gloves, applicators, medical scissors, cold compress, manual, carrying case",49.99,Fabrikam Medical 9 | 8,"Pet First Aid Kit, Goat","Kit includes: Nutri-drench, injectible iron, Vitamin B complex, wound care, bandages, tweezers, thermometer, gloves, applicators, medical scissors, cold compress, manual, carrying case",49.99,Fabrikam Medical 10 | 9,"Pet First Aid Kit, Skunk","Kit includes: Molasses, milk of magnesia, dewormer, wound care, bandages, tweezers, thermometer, gloves, applicators, medical scissors, cold compress, manual, carrying case",49.99,Fabrikam Medical 11 | 10,"Pet First Aid Kit, Reptiles - Large","Kit includes: iodine, magnifying glass, unflavored electrolyte replacement, lice treatment, wound care, bandages, tweezers, thermometer, gloves, applicators, medical scissors, cold compress, manual, carrying case",49.99,Fabrikam Medical 12 | 11,"Pet First Aid Kit, Reptiles - Medium","Kit includes: iodine, magnifying glass, unflavored electrolyte replacement, lice treatment, wound care, bandages, tweezers, thermometer, gloves, applicators, medical scissors, cold compress, manual, carrying case",49.99,Fabrikam Medical 13 | 12,"Pet First Aid Kit, Reptiles - Small","Kit includes: iodine, magnifying glass, unflavored electrolyte replacement, lice treatment, wound care, bandages, tweezers, thermometer, gloves, applicators, medical scissors, cold compress, manual, carrying case",49.99,Fabrikam Medical 14 | 13,Yuzu,For the capybara bath,9.99,Wide World Importers 15 | 14,"Fleece hammock - Christmas print, small",Hammock made with eco-friendly fleece in a Christmas print,9.99,Toy Soldier Pets 16 | 15,"Fleece hammock - Christmas print, medium",Hammock made with eco-friendly fleece in a Christmas print,9.99,Toy Soldier Pets 17 | 16,"Fleece hammock - Christmas print, large",Hammock made with eco-friendly fleece in a Christmas print,9.99,Toy Soldier Pets 18 | 17,"Fleece hammock - Planet print, small",Hammock made with eco-friendly fleece in a planet print,9.99,Toy Soldier Pets 19 | 18,"Fleece hammock - Planet print, medium",Hammock made with eco-friendly fleece in a planet print,9.99,Toy Soldier Pets 20 | 19,"Fleece hammock - Planet print, large",Hammock made with eco-friendly fleece in a planet print,9.99,Toy Soldier Pets 21 | 20,"Fleece hammock - Zebra print, small",Hammock made with eco-friendly fleece in a zebra print,9.99,Toy Soldier Pets 22 | 21,"Fleece hammock - Zebra print, medium",Hammock made with eco-friendly fleece in a zebra print,9.99,Toy Soldier Pets 23 | 22,"Fleece hammock - Zebra print, large",Hammock made with eco-friendly fleece in a zebra print,9.99,Toy Soldier Pets 24 | 23,"Fleece hammock - Leopard print, small",Hammock made with eco-friendly fleece in a leopard print,9.99,Toy Soldier Pets 25 | 24,"Fleece hammock - Leopard print, medium",Hammock made with eco-friendly fleece in a leopard print,9.99,Toy Soldier Pets 26 | 25,"Fleece hammock - Leopard print, large",Hammock made with eco-friendly fleece in a leopard print,9.99,Toy Soldier Pets 27 | 26,"Fleece hammock - Snowflakes print, small",Hammock made with eco-friendly fleece in a snowflakes print,9.99,Toy Soldier Pets 28 | 27,"Fleece hammock - Snowflakes print, medium",Hammock made with eco-friendly fleece in a snowflakes print,9.99,Toy Soldier Pets 29 | 28,"Fleece hammock - Snowflakes print, large",Hammock made with eco-friendly fleece in a snowflakes print,9.99,Toy Soldier Pets 30 | 29,"Fleece hammock - Toy Soldiers print, small",Hammock made with eco-friendly fleece in a toy soldiers print,9.99,Toy Soldier Pets 31 | 30,"Fleece hammock - Toy Soldiers print, medium",Hammock made with eco-friendly fleece in a toy soldiers print,9.99,Toy Soldier Pets 32 | 31,"Fleece hammock - Toy Soldiers print, large",Hammock made with eco-friendly fleece in a toy soldiers print,9.99,Toy Soldier Pets 33 | 32,"Fleece hammock - Fish print, small",Hammock made with eco-friendly fleece in a fish print,9.99,Toy Soldier Pets 34 | 33,"Fleece hammock - Fish print, medium",Hammock made with eco-friendly fleece in a fish print,9.99,Toy Soldier Pets 35 | 34,"Fleece hammock - Fish print, large",Hammock made with eco-friendly fleece in a fish print,9.99,Toy Soldier Pets 36 | 35,"Fleece hammock - Leaves print, small",Hammock made with eco-friendly fleece in a leaves print,9.99,Toy Soldier Pets 37 | 36,"Fleece hammock - Leaves print, medium",Hammock made with eco-friendly fleece in a leaves print,9.99,Toy Soldier Pets 38 | 37,"Fleece hammock - Leaves print, large",Hammock made with eco-friendly fleece in a leaves print,9.99,Toy Soldier Pets 39 | 38,"Fleece hammock - Chevron print, small",Hammock made with eco-friendly fleece in a chevron print,9.99,Toy Soldier Pets 40 | 39,"Fleece hammock - Chevron print, medium",Hammock made with eco-friendly fleece in a chevron print,9.99,Toy Soldier Pets 41 | 40,"Fleece hammock - Chevron print, large",Hammock made with eco-friendly fleece in a chevron print,9.99,Toy Soldier Pets 42 | 41,Glider chew toy,Chew toy made of rubber in the shape of a glider,4.95,Wingtip Toys 43 | 42,Fire truck chew toy,Chew toy made of rubber in the shape of a fire truck,6.95,Wingtip Toys 44 | 43,Fast car chew toy,Chew toy made of rubber in the shape of a fast car,8.95,Wingtip Toys 45 | 44,Zeppelin chew toy,Chew toy made of bamboo in the shape of a zeppelin,7.99,Tailspin Toys 46 | 45,Propeller plane chew toy,Chew toy made of bamboo in the shape of a propeller plane,6.99,Tailspin Toys 47 | 46,Rocket chew toy,Chew toy made of bamboo in the shape of a rocket,4.99,Tailspin Toys 48 | 47,Fountain grass plant,For use in freshwater aquariums,14.95,Contoso 49 | 48,Broadleaf sword plant,For use in freshwater aquariums,3.99,Contoso 50 | 49,Brazilian sword plant,For use in freshwater aquariums,4.99,Contoso 51 | 50,Vallisenria Americana plant,For use in freshwater aquariums,3.99,Contoso 52 | 51,Vallisneria Nana plant,For use in freshwater aquariums,2.99,Contoso 53 | 52,Vallisneria Contortionist plant,For use in freshwater aquariums,4.99,Contoso 54 | 53,Halimeda plant,For use in saltwater aquariums,14.99,Wide World Importers 55 | 54,Dragon's Tongue algae,For use in saltwater aquariums,54.99,Wide World Importers 56 | 55,Turtle grass shoots,For use in saltwater aquariums,29.99,Wide World Importers 57 | 56,Mermaid's Fan,For use in saltwater aquariums,12.99,Wide World Importers 58 | 57,Shaving brush plant,For use in saltwater aquariums,13.99,Wide World Importers 59 | -------------------------------------------------------------------------------- /data/SampleRelationalData.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/data/SampleRelationalData.xlsx -------------------------------------------------------------------------------- /data/TransformExcel.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "kernelspec": { 4 | "name": "python3", 5 | "display_name": "Python 3", 6 | "language": "python" 7 | }, 8 | "language_info": { 9 | "name": "python", 10 | "version": "3.8.10", 11 | "mimetype": "text/x-python", 12 | "codemirror_mode": { 13 | "name": "ipython", 14 | "version": 3 15 | }, 16 | "pygments_lexer": "ipython3", 17 | "nbconvert_exporter": "python", 18 | "file_extension": ".py" 19 | } 20 | }, 21 | "nbformat_minor": 2, 22 | "nbformat": 4, 23 | "cells": [ 24 | { 25 | "cell_type": "code", 26 | "source": [ 27 | "import pandas as pd\r\n", 28 | "products = pd.read_csv(\"ProductsWithManufacturers.csv\")\r\n", 29 | "products['type'] = 'product'\r\n", 30 | "products.columns = ['id','name','description','msrp','manufacturer','type']\r\n", 31 | "products['id'] = products['id'].astype(str)" 32 | ], 33 | "metadata": { 34 | "azdata_cell_guid": "00128ae1-4666-4f3d-8a2f-78ac3029cb4a", 35 | "tags": [] 36 | }, 37 | "outputs": [ 38 | { 39 | "traceback": [ 40 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 41 | "\u001b[1;31mAttributeError\u001b[0m Traceback (most recent call last)", 42 | "\u001b[1;32mC:\\azuredatastudio-python\\lib\\site-packages\\pandas\\core\\generic.py\u001b[0m in \u001b[0;36m__setattr__\u001b[1;34m(self, name, value)\u001b[0m\n\u001b[0;32m 5517\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m-> 5518\u001b[1;33m \u001b[0mobject\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m__setattr__\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mname\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mvalue\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 5519\u001b[0m \u001b[1;32mexcept\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0mAttributeError\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", 43 | "\u001b[1;31mAttributeError\u001b[0m: can't set attribute", 44 | "\nDuring handling of the above exception, another exception occurred:\n", 45 | "\u001b[1;31mAttributeError\u001b[0m Traceback (most recent call last)", 46 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 3\u001b[0m \u001b[0mproducts\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m'type'\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;34m'product'\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 4\u001b[0m \u001b[0mproducts\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcolumns\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;34m'id'\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;34m'name'\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;34m'description'\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;34m'msrp'\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;34m'manufacturer'\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;34m'type'\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 5\u001b[1;33m \u001b[0mproducts\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m'id'\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdtype\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;34m\"string\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 47 | "\u001b[1;32mC:\\azuredatastudio-python\\lib\\site-packages\\pandas\\core\\generic.py\u001b[0m in \u001b[0;36m__setattr__\u001b[1;34m(self, name, value)\u001b[0m\n\u001b[0;32m 5526\u001b[0m \u001b[0mstacklevel\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m2\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 5527\u001b[0m )\n\u001b[1;32m-> 5528\u001b[1;33m \u001b[0mobject\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m__setattr__\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mname\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mvalue\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 5529\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 5530\u001b[0m \u001b[1;33m@\u001b[0m\u001b[0mfinal\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", 48 | "\u001b[1;31mAttributeError\u001b[0m: can't set attribute" 49 | ], 50 | "ename": "AttributeError", 51 | "evalue": "can't set attribute", 52 | "output_type": "error" 53 | } 54 | ], 55 | "execution_count": 2 56 | }, 57 | { 58 | "cell_type": "code", 59 | "source": [ 60 | "products.to_json('products.json',orient='records',lines=True)" 61 | ], 62 | "metadata": { 63 | "azdata_cell_guid": "6fee7e11-12f2-4e5b-9bcd-eacedad09e0d" 64 | }, 65 | "outputs": [], 66 | "execution_count": 2 67 | } 68 | ] 69 | } -------------------------------------------------------------------------------- /demos/.gitignore: -------------------------------------------------------------------------------- 1 | ############################## 2 | ## Java 3 | ############################## 4 | .mtj.tmp/ 5 | *.class 6 | *.jar 7 | *.war 8 | *.ear 9 | *.nar 10 | hs_err_pid* 11 | 12 | ############################## 13 | ## Maven 14 | ############################## 15 | target/ 16 | pom.xml.tag 17 | pom.xml.releaseBackup 18 | pom.xml.versionsBackup 19 | pom.xml.next 20 | pom.xml.bak 21 | release.properties 22 | dependency-reduced-pom.xml 23 | buildNumber.properties 24 | .mvn/timing.properties 25 | .mvn/wrapper/maven-wrapper.jar 26 | 27 | ############################## 28 | ## Gradle 29 | ############################## 30 | bin/ 31 | build/ 32 | .gradle 33 | .gradletasknamecache 34 | gradle-app.setting 35 | !gradle-wrapper.jar 36 | 37 | ############################## 38 | ## IntelliJ 39 | ############################## 40 | out/ 41 | .idea/ 42 | .idea_modules/ 43 | *.iml 44 | *.ipr 45 | *.iws 46 | 47 | ############################## 48 | ## Eclipse 49 | ############################## 50 | .settings/ 51 | bin/ 52 | tmp/ 53 | .metadata 54 | .classpath 55 | .project 56 | *.tmp 57 | *.bak 58 | *.swp 59 | *~.nib 60 | local.properties 61 | .loadpath 62 | .factorypath 63 | 64 | ############################## 65 | ## NetBeans 66 | ############################## 67 | nbproject/private/ 68 | build/ 69 | nbbuild/ 70 | dist/ 71 | nbdist/ 72 | nbactions.xml 73 | nb-configuration.xml 74 | 75 | ############################## 76 | ## Visual Studio Code 77 | ############################## 78 | 79 | .code-workspace 80 | 81 | ############################## 82 | ## OS X 83 | ############################## 84 | .DS_Store 85 | 86 | ############################## 87 | ## Visual Studio Code 88 | ############################## 89 | bin 90 | obj 91 | csx 92 | .vs 93 | edge 94 | Publish 95 | 96 | *.user 97 | *.suo 98 | *.cscfg 99 | *.Cache 100 | project.lock.json 101 | 102 | /packages 103 | /TestResults 104 | 105 | /tools/NuGet.exe 106 | /App_Data 107 | /secrets 108 | /data 109 | .secrets 110 | appsettings.json 111 | local.settings.json 112 | 113 | node_modules 114 | dist 115 | 116 | # Local python packages 117 | .python_packages/ 118 | 119 | # Python Environments 120 | .env 121 | .venv 122 | env/ 123 | venv/ 124 | ENV/ 125 | env.bak/ 126 | venv.bak/ 127 | 128 | # Byte-compiled / optimized / DLL files 129 | __pycache__/ 130 | *.py[cod] 131 | *$py.class 132 | 133 | HELP.md 134 | target/ 135 | !.mvn/wrapper/maven-wrapper.jar 136 | !**/src/main/**/target/ 137 | !**/src/test/**/target/ 138 | 139 | ### STS ### 140 | .apt_generated 141 | .classpath 142 | .factorypath 143 | .project 144 | .settings 145 | .springBeans 146 | .sts4-cache 147 | 148 | ### IntelliJ IDEA ### 149 | .idea 150 | *.iws 151 | *.iml 152 | *.ipr 153 | 154 | ### NetBeans ### 155 | /nbproject/private/ 156 | /nbbuild/ 157 | /dist/ 158 | /nbdist/ 159 | /.nb-gradle/ 160 | build/ 161 | !**/src/main/**/build/ 162 | !**/src/test/**/build/ 163 | 164 | ### VS Code ### 165 | .vscode/ 166 | 167 | # Build output 168 | target/ 169 | *.class 170 | 171 | # Log file 172 | *.log 173 | 174 | # BlueJ files 175 | *.ctxt 176 | 177 | # Mobile Tools for Java (J2ME) 178 | .mtj.tmp/ 179 | 180 | # Package Files # 181 | *.jar 182 | *.war 183 | *.ear 184 | *.zip 185 | *.tar.gz 186 | *.rar 187 | 188 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 189 | hs_err_pid* 190 | 191 | # IDE 192 | .idea/ 193 | *.iml 194 | .settings/ 195 | .project 196 | .classpath 197 | 198 | # macOS 199 | .DS_Store 200 | 201 | # Azure Functions 202 | local.settings.json 203 | bin/ 204 | obj/ 205 | -------------------------------------------------------------------------------- /demos/cosmos-db/demo/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.3/apache-maven-3.8.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar 3 | -------------------------------------------------------------------------------- /demos/cosmos-db/demo/README.md: -------------------------------------------------------------------------------- 1 | # Java Setup 2 | 3 | There are a few things you need to set up before you can run this code. 4 | 5 | 1. Clone this Repository 6 | 2. Set up Environment Variables. 7 | 3. Create the instance of Azure Cosmos DB Core (SQL) API. 8 | 4. Add secrets to Azure Key Vault. 9 | 5. Run the code. 10 | 11 | ## Set up Azure Identity Environment Variables 12 | 13 | When going through the walk through for Hello World with Java Key Vault, you create a service principal called `java-keyvault-demo-sp`. You will need the following information: 14 | 15 | * AppId 16 | * Password 17 | * TenantId 18 | * Azure Key Vault URL 19 | 20 | Then, set up the following environment variables with these values: 21 | 22 | * AZURE_CLIENT_ID - AppId 23 | * AZURE_TENANT_ID - TenantId 24 | * AZURE_CLIENT_SECRET - Password 25 | * AZURE_KEYVAULT_URL - Azure Key Vault URL 26 | 27 | ## Create an Azure Cosmos DB Core (SQL) API instance 28 | 29 | To create an Azure Cosmos DB Core (SQL) API Free Tier account, use the following command: 30 | 31 | ```azurecli 32 | az cosmosdb create -n "pet-supplies-demo" -g "java-keyvault-demo-rg" --enable-free-tier true --default-consistency-level "Session" 33 | ``` 34 | 35 | ## Add Secrets to Azure Key Vault 36 | 37 | Once the Azure Cosmos DB Core (SQL) API instance is created, then add these secrets to Azure Key Vault. **application.properties** is configured to look for the following secrets: 38 | 39 | * azure-documentdb-uri 40 | * azure-documentdb-key 41 | * azure-documentdb-database 42 | 43 | ### Document DB URI 44 | 45 | Use the following command to store the URI in the secret named **azure-documentdb-uri**: 46 | 47 | ```azurecli 48 | az keyvault secret set --vault-name java-keyvault-demo-kv --name "azure-documentdb-uri" --value (az cosmosdb show --name pet-supplies-demo -g java-keyvault-demo-rg --query "readLocations[0].documentEndpoint" -o tsv) 49 | ``` 50 | 51 | ## Document DB Key 52 | 53 | This is for the read and write key. Use the following command to store the URI in the secret named **azure-documentdb-uri**: 54 | 55 | ```azurecli 56 | az keyvault secret set --vault-name java-keyvault-demo-kv --name "azure-documentdb-key" --value (az cosmosdb keys list --name pet-supplies-demo -g java-keyvault-demo-rg --query "primaryMasterKey") 57 | ``` 58 | 59 | ## DocumentDB Database 60 | 61 | Use the following command to store the URI in the secret named **azure-documentdb-database**: 62 | 63 | ```azurecli 64 | az keyvault secret set --vault-name java-keyvault-demo-kv --name "azure-documentdb-database" --value "pet-supplies-demo" 65 | ``` 66 | 67 | ## Running the Code 68 | 69 | Run `mvn install` to install dependencies. 70 | 71 | Run `mvn spring-boot:run` to run locally and access the api at http://localhost:8080. 72 | 73 | ## Deploying to an Azure App Service 74 | 75 | To deploy this to an Azure App Service, use the [Maven Plugin for Azure App Service](https://github.com/microsoft/azure-maven-plugins/blob/develop/azure-webapp-maven-plugin/). This tool will create the resources if they do not exist. 76 | 77 | In the **pom.xml** file, update the `` section for the following properties: 78 | 79 | * azure.webapp.AppName - App name 80 | * azure.webapp.appServicePlanName - App Service Plan Name 81 | * azure.webapp.region - region code - such as `eastus`, `westus`, etc. 82 | * azure.webapp.resourceGroup - resource group name 83 | 84 | Once the configuration information is updated for your values, deploy the application with the following command: 85 | 86 | ```bash 87 | mvn package azure-webapp:deploy 88 | ``` 89 | 90 | ## Additional Notes 91 | 92 | * This project was created using [Spring Initializr](https://start.spring.io). 93 | 94 | * If using Visual Studio Code, [try the VS Code Spring initializr extension](https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-spring-initializr). 95 | 96 | * If using Visual Studio Code, [install the Lombok extension](https://marketplace.visualstudio.com/items?itemName=GabrielBB.vscode-lombok) for the getters and setters. 97 | 98 | * The Spring packages to work with Azure Cosmos DB and Azure have dependencies that require Spring Boot >= 2.2.11.RELEASE and < 2.7.0-M1. 99 | 100 | ## Tear Down 101 | 102 | * Remove the resource group created for this code. 103 | * Delete the service principal created for this exercise. -------------------------------------------------------------------------------- /demos/cosmos-db/demo/mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM https://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM set title of command window 39 | title %0 40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' 41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 42 | 43 | @REM set %HOME% to equivalent of $HOME 44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 45 | 46 | @REM Execute a user defined script before this one 47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 49 | if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* 50 | if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* 51 | :skipRcPre 52 | 53 | @setlocal 54 | 55 | set ERROR_CODE=0 56 | 57 | @REM To isolate internal variables from possible post scripts, we use another setlocal 58 | @setlocal 59 | 60 | @REM ==== START VALIDATION ==== 61 | if not "%JAVA_HOME%" == "" goto OkJHome 62 | 63 | echo. 64 | echo Error: JAVA_HOME not found in your environment. >&2 65 | echo Please set the JAVA_HOME variable in your environment to match the >&2 66 | echo location of your Java installation. >&2 67 | echo. 68 | goto error 69 | 70 | :OkJHome 71 | if exist "%JAVA_HOME%\bin\java.exe" goto init 72 | 73 | echo. 74 | echo Error: JAVA_HOME is set to an invalid directory. >&2 75 | echo JAVA_HOME = "%JAVA_HOME%" >&2 76 | echo Please set the JAVA_HOME variable in your environment to match the >&2 77 | echo location of your Java installation. >&2 78 | echo. 79 | goto error 80 | 81 | @REM ==== END VALIDATION ==== 82 | 83 | :init 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 122 | 123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" 124 | 125 | FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( 126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B 127 | ) 128 | 129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data. 131 | if exist %WRAPPER_JAR% ( 132 | if "%MVNW_VERBOSE%" == "true" ( 133 | echo Found %WRAPPER_JAR% 134 | ) 135 | ) else ( 136 | if not "%MVNW_REPOURL%" == "" ( 137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" 138 | ) 139 | if "%MVNW_VERBOSE%" == "true" ( 140 | echo Couldn't find %WRAPPER_JAR%, downloading it ... 141 | echo Downloading from: %DOWNLOAD_URL% 142 | ) 143 | 144 | powershell -Command "&{"^ 145 | "$webclient = new-object System.Net.WebClient;"^ 146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ 147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ 148 | "}"^ 149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ 150 | "}" 151 | if "%MVNW_VERBOSE%" == "true" ( 152 | echo Finished downloading %WRAPPER_JAR% 153 | ) 154 | ) 155 | @REM End of extension 156 | 157 | @REM Provide a "standardized" way to retrieve the CLI args that will 158 | @REM work with both Windows and non-Windows executions. 159 | set MAVEN_CMD_LINE_ARGS=%* 160 | 161 | %MAVEN_JAVA_EXE% ^ 162 | %JVM_CONFIG_MAVEN_PROPS% ^ 163 | %MAVEN_OPTS% ^ 164 | %MAVEN_DEBUG_OPTS% ^ 165 | -classpath %WRAPPER_JAR% ^ 166 | "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ 167 | %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 168 | if ERRORLEVEL 1 goto error 169 | goto end 170 | 171 | :error 172 | set ERROR_CODE=1 173 | 174 | :end 175 | @endlocal & set ERROR_CODE=%ERROR_CODE% 176 | 177 | if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost 178 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 179 | if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" 180 | if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" 181 | :skipRcPost 182 | 183 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 184 | if "%MAVEN_BATCH_PAUSE%"=="on" pause 185 | 186 | if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% 187 | 188 | cmd /C exit /B %ERROR_CODE% 189 | -------------------------------------------------------------------------------- /demos/cosmos-db/demo/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.6.1 9 | 10 | 11 | com.example 12 | demo 13 | 0.0.1-SNAPSHOT 14 | demo 15 | cosmos-db 16 | 17 | 11 18 | pet-supplies-app 19 | 3.12.1 20 | ms-cosmos-db-java-guide 21 | ms-cosmos-db-java-guide 22 | westus 23 | ms-cosmos-db-java-guide 24 | 2.3.0 25 | 26 | 27 | 28 | org.springframework.boot 29 | spring-boot-starter-webflux 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter-thymeleaf 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-starter-web 38 | 39 | 40 | org.springframework.cloud 41 | spring-cloud-starter-config 42 | 3.1.0 43 | 44 | 45 | org.springframework.cloud 46 | spring-cloud-starter-netflix-eureka-client 47 | 3.1.0 48 | 49 | 50 | com.azure.spring 51 | azure-spring-boot-starter-cosmos 52 | 53 | 54 | com.azure 55 | azure-cosmos 56 | 4.22.0 57 | 58 | 59 | org.springframework.boot 60 | spring-boot-devtools 61 | runtime 62 | true 63 | 64 | 65 | org.springframework.boot 66 | spring-boot-starter-test 67 | test 68 | 69 | 70 | org.projectlombok 71 | lombok 72 | true 73 | 74 | 75 | io.projectreactor 76 | reactor-test 77 | test 78 | 79 | 80 | javax.annotation 81 | javax.annotation-api 82 | 1.3.2 83 | 84 | 85 | 86 | 87 | 88 | com.azure.spring 89 | azure-spring-boot-bom 90 | ${azure.version} 91 | pom 92 | import 93 | 94 | 95 | 96 | 97 | 98 | 99 | org.springframework.boot 100 | spring-boot-maven-plugin 101 | 102 | 103 | 104 | org.projectlombok 105 | lombok 106 | 107 | 108 | 109 | 110 | 111 | com.microsoft.azure 112 | azure-webapp-maven-plugin 113 | ${azure.webapp.version} 114 | 115 | v2 116 | ${azure.webapp.resourceGroup} 117 | ${azure.webapp.appServicePlanName} 118 | ${azure.webapp.appName} 119 | ${azure.webapp.region} 120 | F1 121 | 122 | Linux 123 | Java ${java.version} 124 | Java SE 125 | 126 | 127 | 128 | AZURE_COSMOS_URI 129 | ${AZURE_COSMOS_URI} 130 | 131 | 132 | AZURE_COSMOS_KEY 133 | ${AZURE_COSMOS_KEY} 134 | 135 | 136 | 137 | 138 | 139 | ${project.basedir}/target 140 | 141 | *.jar 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | com.microsoft.azure 150 | azure-spring-cloud-maven-plugin 151 | 1.8.0 152 | 153 | ms-cosmos-db-java-guide-spring 154 | ${azure.springcloud.appName} 155 | true 156 | 157 | 1 158 | 1 159 | 1 160 | Java 11 161 | 162 | 163 | 164 | 165 | 166 | ${project.basedir}/target 167 | 168 | *.jar 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /demos/cosmos-db/demo/src/main/java/com/example/demo/DemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class DemoApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(DemoApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /demos/cosmos-db/demo/src/main/java/com/example/demo/config/CosmosConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.config; 2 | 3 | import com.azure.cosmos.ChangeFeedProcessorBuilder; 4 | import com.azure.cosmos.CosmosAsyncClient; 5 | import com.azure.cosmos.CosmosAsyncContainer; 6 | import com.azure.cosmos.CosmosAsyncDatabase; 7 | import com.azure.cosmos.CosmosClientBuilder; 8 | import com.azure.cosmos.DirectConnectionConfig; 9 | import com.azure.cosmos.GatewayConnectionConfig; 10 | import com.azure.cosmos.models.ChangeFeedProcessorOptions; 11 | import com.azure.spring.data.cosmos.config.AbstractCosmosConfiguration; 12 | import com.azure.spring.data.cosmos.config.CosmosConfig; 13 | import com.azure.spring.data.cosmos.core.ResponseDiagnostics; 14 | import com.azure.spring.data.cosmos.core.ResponseDiagnosticsProcessor; 15 | import com.azure.spring.data.cosmos.repository.config.EnableCosmosRepositories; 16 | import com.fasterxml.jackson.databind.JsonNode; 17 | import org.springframework.context.annotation.Bean; 18 | import org.springframework.context.annotation.Configuration; 19 | import org.springframework.context.annotation.Primary; 20 | import org.slf4j.Logger; 21 | import org.slf4j.LoggerFactory; 22 | import org.springframework.beans.factory.annotation.Value; 23 | import org.springframework.lang.Nullable; 24 | 25 | @Configuration 26 | @EnableCosmosRepositories 27 | public class CosmosConfiguration extends AbstractCosmosConfiguration { 28 | 29 | // These azure.cosmos variables are coming from the Config server if in Azure Spring Apps. 30 | // Otherwise, for development purposes, these values are stored in application-default.properties. 31 | @Value("${azure.cosmos.uri}") 32 | private String uri; 33 | 34 | @Value("${azure.cosmos.key}") 35 | private String key; 36 | 37 | @Value("${azure.cosmos.database}") 38 | private String dbName; 39 | 40 | @Value("${azure.cosmos.feed-container}") 41 | private String feedContainer; 42 | 43 | @Value("${azure.cosmos.lease-container}") 44 | private String leaseContainer; 45 | 46 | private CosmosAsyncClient client; 47 | private CosmosAsyncDatabase database; 48 | private CosmosAsyncContainer container; 49 | 50 | private static final Logger logger = LoggerFactory.getLogger(CosmosConfiguration.class); 51 | 52 | public CosmosConfiguration() {} 53 | 54 | @Bean 55 | public CosmosClientBuilder getCosmosClientBuilder() { 56 | DirectConnectionConfig directConnectionConfig = new DirectConnectionConfig(); 57 | GatewayConnectionConfig gatewayConnectionConfig = new GatewayConnectionConfig(); 58 | return new CosmosClientBuilder() 59 | .endpoint(uri) 60 | .key(key) 61 | .contentResponseOnWriteEnabled(true) 62 | .directMode(directConnectionConfig, gatewayConnectionConfig); 63 | } 64 | 65 | @Bean 66 | public ChangeFeedProcessorBuilder getChangeFeedProcessor() { 67 | CosmosAsyncClient client = getCosmosClientBuilder().buildAsyncClient(); 68 | CosmosAsyncDatabase database = client.getDatabase(this.dbName); 69 | CosmosAsyncContainer feedContainer = database.getContainer(this.feedContainer); 70 | CosmosAsyncContainer leaseContainer = database.getContainer(this.leaseContainer); 71 | ChangeFeedProcessorOptions cfOptions = new ChangeFeedProcessorOptions(); 72 | return new ChangeFeedProcessorBuilder() 73 | .options(cfOptions) 74 | .hostName(this.uri) 75 | .feedContainer(feedContainer) 76 | .leaseContainer(leaseContainer) 77 | .handleChanges(docs -> { 78 | for (JsonNode item : docs) { 79 | System.out.println(item); 80 | } 81 | }); 82 | } 83 | 84 | @Primary 85 | @Bean 86 | public CosmosAsyncClient getClient(){ 87 | return client = getCosmosClientBuilder().buildAsyncClient(); 88 | } 89 | 90 | @Bean 91 | public CosmosAsyncDatabase CosmosDatabaseBuilder() { 92 | database = client.getDatabase(this.dbName); 93 | return database; 94 | } 95 | 96 | @Bean 97 | public CosmosAsyncContainer CosmosContainerBuilder() { 98 | container = database.getContainer(this.feedContainer); 99 | return container; 100 | } 101 | 102 | @Override 103 | public CosmosConfig cosmosConfig() { 104 | return CosmosConfig.builder() 105 | .responseDiagnosticsProcessor(new ResponseDiagnosticsProcessorImplementation()) 106 | .build(); 107 | } 108 | 109 | @Override 110 | protected String getDatabaseName() { 111 | return dbName; 112 | } 113 | 114 | private static class ResponseDiagnosticsProcessorImplementation implements ResponseDiagnosticsProcessor { 115 | 116 | @Override 117 | public void processResponseDiagnostics(@Nullable ResponseDiagnostics responseDiagnostics) { 118 | // LOGGER.info("Response Diagnostics {}", responseDiagnostics); 119 | } 120 | } 121 | 122 | } -------------------------------------------------------------------------------- /demos/cosmos-db/demo/src/main/java/com/example/demo/controller/BulkController.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.controller; 2 | 3 | import java.util.List; 4 | 5 | import com.azure.cosmos.models.CosmosBulkItemResponse; 6 | import com.example.demo.model.BaseModel; 7 | import com.example.demo.service.BulkExecutorService; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.web.bind.annotation.DeleteMapping; 10 | import org.springframework.web.bind.annotation.PostMapping; 11 | import org.springframework.web.bind.annotation.PutMapping; 12 | import org.springframework.web.bind.annotation.RequestBody; 13 | import org.springframework.web.bind.annotation.RequestMapping; 14 | import org.springframework.web.bind.annotation.RestController; 15 | 16 | @RestController 17 | @RequestMapping("/api/bulk") 18 | public class BulkController { 19 | 20 | @Autowired 21 | BulkExecutorService bulkExecutorService; 22 | 23 | @PostMapping(produces = "application/json", consumes = "application/json") 24 | public CosmosBulkItemResponse create(@RequestBody List documents) { 25 | return this.bulkExecutorService.bulkImport(documents); 26 | } 27 | 28 | @PutMapping(produces = "application/json", consumes = "application/json") 29 | public CosmosBulkItemResponse update(@RequestBody List updates) { 30 | return this.bulkExecutorService.bulkUpdate(updates); 31 | } 32 | 33 | @DeleteMapping(produces = "application/json", consumes = "application/json") 34 | public CosmosBulkItemResponse delete(@RequestBody List deleteItems){ 35 | return this.bulkExecutorService.bulkDelete(deleteItems); 36 | } 37 | } -------------------------------------------------------------------------------- /demos/cosmos-db/demo/src/main/java/com/example/demo/controller/ChangeFeedController.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.controller; 2 | 3 | import com.example.demo.service.ChangeFeedService; 4 | import com.example.demo.model.Product; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.http.MediaType; 8 | import org.springframework.web.bind.annotation.GetMapping; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.bind.annotation.RestController; 11 | import reactor.core.publisher.Flux; 12 | 13 | @RestController 14 | @RequestMapping("/api/changefeed") 15 | public class ChangeFeedController { 16 | 17 | @Autowired 18 | ChangeFeedService changeFeedService; 19 | 20 | @GetMapping(produces = MediaType.TEXT_EVENT_STREAM_VALUE) 21 | public Flux read() { 22 | return changeFeedService.changedProducts; 23 | } 24 | } -------------------------------------------------------------------------------- /demos/cosmos-db/demo/src/main/java/com/example/demo/controller/CustomerController.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.controller; 2 | 3 | import com.example.demo.service.CustomerService; 4 | import com.example.demo.model.Customer; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.web.bind.annotation.DeleteMapping; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | import org.springframework.web.bind.annotation.PathVariable; 9 | import org.springframework.web.bind.annotation.PostMapping; 10 | import org.springframework.web.bind.annotation.PutMapping; 11 | import org.springframework.web.bind.annotation.RequestBody; 12 | import org.springframework.web.bind.annotation.RequestMapping; 13 | import org.springframework.web.bind.annotation.RequestParam; 14 | import org.springframework.web.bind.annotation.RestController; 15 | import reactor.core.publisher.Flux; 16 | import reactor.core.publisher.Mono; 17 | 18 | @RestController 19 | @RequestMapping("/api/customers") 20 | public class CustomerController { 21 | 22 | @Autowired 23 | CustomerService customerService; 24 | 25 | @PostMapping(produces = "application/json", consumes = "application/json") 26 | public Mono create(@RequestBody Customer customer) { 27 | return this.customerService.save(customer); 28 | } 29 | 30 | @GetMapping 31 | @PostMapping(produces = "application/json") 32 | public Flux read( 33 | @RequestParam(name = "key", defaultValue = "customer") String key) { 34 | return customerService.findAll(key); 35 | } 36 | 37 | @GetMapping(path = "/{customerId}", produces = "application/json") 38 | public Mono findById( 39 | @PathVariable(name = "customerId") String customerId, 40 | @RequestParam(name = "key", defaultValue = "customer") String key) { 41 | return this.customerService.findById(customerId, key); 42 | } 43 | 44 | @PutMapping(produces = "application/json", consumes = "application/json") 45 | public Mono update(@RequestBody Customer customer) { 46 | return this.customerService.save(customer); 47 | } 48 | 49 | @DeleteMapping(path = "/{customerId}", produces = "application/json") 50 | public Mono delete( 51 | @PathVariable(name = "customerId") String customerId, 52 | @RequestParam(name = "key", defaultValue = "customer") String key) { 53 | return this.customerService.deleteById(customerId, key); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /demos/cosmos-db/demo/src/main/java/com/example/demo/controller/ManufacturerController.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.controller; 2 | 3 | import com.example.demo.service.ManufacturerService; 4 | import com.example.demo.model.Manufacturer; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.web.bind.annotation.DeleteMapping; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | import org.springframework.web.bind.annotation.PathVariable; 9 | import org.springframework.web.bind.annotation.PostMapping; 10 | import org.springframework.web.bind.annotation.PutMapping; 11 | import org.springframework.web.bind.annotation.RequestBody; 12 | import org.springframework.web.bind.annotation.RequestMapping; 13 | import org.springframework.web.bind.annotation.RequestParam; 14 | import org.springframework.web.bind.annotation.RestController; 15 | import reactor.core.publisher.Flux; 16 | import reactor.core.publisher.Mono; 17 | 18 | @RestController 19 | @RequestMapping("/api/manufacturers") 20 | public class ManufacturerController { 21 | 22 | @Autowired 23 | private ManufacturerService manufacturerService; 24 | 25 | @PostMapping(produces = "application/json", consumes = "application/json") 26 | public Mono create(@RequestBody Manufacturer manufacturer) { 27 | return this.manufacturerService.save(manufacturer); 28 | } 29 | 30 | @GetMapping 31 | public Flux read( 32 | @RequestParam(name = "key", defaultValue = "manufacturer") String key) { 33 | return manufacturerService.findAll(key); 34 | } 35 | 36 | @GetMapping(path = "/{manufacturerId}", produces = "application/json") 37 | public Mono findById( 38 | @PathVariable(name = "manufacturerId") String manufacturerId, 39 | @RequestParam(name = "key", defaultValue = "manufacturer") String key) { 40 | return this.manufacturerService.findById(manufacturerId, key); 41 | } 42 | 43 | @PutMapping(produces = "application/json", consumes = "application/json") 44 | public Mono update(@RequestBody Manufacturer manufacturer) { 45 | return this.manufacturerService.save(manufacturer); 46 | } 47 | 48 | @DeleteMapping(path = "/{manufacturerId}", produces = "application/json") 49 | public Mono delete( 50 | @PathVariable("manufacturerId") String manufacturerId, 51 | @RequestParam(name = "key", defaultValue = "manufacturer") String key) { 52 | return this.manufacturerService.deleteById(manufacturerId, key); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /demos/cosmos-db/demo/src/main/java/com/example/demo/controller/ProductController.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.controller; 2 | 3 | import com.example.demo.service.ProductService; 4 | import com.example.demo.model.Product; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.web.bind.annotation.DeleteMapping; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | import org.springframework.web.bind.annotation.PatchMapping; 9 | import org.springframework.web.bind.annotation.PathVariable; 10 | import org.springframework.web.bind.annotation.PostMapping; 11 | import org.springframework.web.bind.annotation.PutMapping; 12 | import org.springframework.web.bind.annotation.RequestBody; 13 | import org.springframework.web.bind.annotation.RequestMapping; 14 | import org.springframework.web.bind.annotation.RequestParam; 15 | import org.springframework.web.bind.annotation.RestController; 16 | import reactor.core.publisher.Flux; 17 | import reactor.core.publisher.Mono; 18 | 19 | @RestController 20 | @RequestMapping("/api/products") 21 | public class ProductController { 22 | 23 | @Autowired 24 | private ProductService productService; 25 | 26 | @PostMapping(produces = "application/json", consumes = "application/json") 27 | public Mono create(@RequestBody Product product) { 28 | return this.productService.save(product); 29 | } 30 | 31 | @GetMapping(produces = "application/json") 32 | public Flux read(@RequestParam(name = "key", defaultValue = "product") String key) { 33 | return productService.findAll(key); 34 | } 35 | 36 | @GetMapping(path = "/{productId}", produces = "application/json") 37 | public Mono findById( 38 | @PathVariable("productId") String productId, 39 | @RequestParam(name = "key", defaultValue = "product") String key) { 40 | return this.productService.findById(productId, key); 41 | } 42 | 43 | @PutMapping(produces = "application/json", consumes = "application/json") 44 | public Mono update(@RequestBody Product product) { 45 | return this.productService.save(product); 46 | } 47 | 48 | @PatchMapping(produces = "application/json", consumes = "application/json") 49 | public void saveMsrp(@RequestBody Product product) { 50 | this.productService.saveMsrp(product); 51 | } 52 | 53 | @DeleteMapping(path = "/{productId}", produces = "application/json") 54 | public Mono delete( 55 | @PathVariable("productId") String productId, 56 | @RequestParam(name = "key", defaultValue = "product") String key) { 57 | return this.productService.deleteById(productId, key); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /demos/cosmos-db/demo/src/main/java/com/example/demo/controller/WishlistController.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.controller; 2 | 3 | import com.example.demo.service.WishlistService; 4 | import com.example.demo.model.Wishlist; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.web.bind.annotation.DeleteMapping; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | import org.springframework.web.bind.annotation.PathVariable; 9 | import org.springframework.web.bind.annotation.PostMapping; 10 | import org.springframework.web.bind.annotation.PutMapping; 11 | import org.springframework.web.bind.annotation.RequestBody; 12 | import org.springframework.web.bind.annotation.RequestMapping; 13 | import org.springframework.web.bind.annotation.RequestParam; 14 | import org.springframework.web.bind.annotation.RestController; 15 | import reactor.core.publisher.Flux; 16 | import reactor.core.publisher.Mono; 17 | 18 | @RestController 19 | @RequestMapping("/api/wishlists") 20 | public class WishlistController { 21 | 22 | @Autowired 23 | private WishlistService wishlistService; 24 | 25 | @PostMapping(produces = "application/json", consumes = "application/json") 26 | public Mono create(@RequestBody Wishlist wishlist) { 27 | return this.wishlistService.save(wishlist); 28 | } 29 | 30 | @GetMapping(produces = "application/json") 31 | public Flux read(@RequestParam(name = "key", defaultValue = "wishlist") String key) { 32 | return wishlistService.findAll(key); 33 | } 34 | 35 | @GetMapping(path = "/products/{productId}", produces = "application/json") 36 | public Flux findByProductId(@PathVariable("productId") String productId) { 37 | return wishlistService.findByProductId(productId); 38 | } 39 | 40 | @GetMapping(path = "/{wishlistId}", produces = "application/json") 41 | public Mono findById( 42 | @PathVariable("wishlistId") String wishlistId, 43 | @RequestParam(name = "key", defaultValue = "wishlist") String key) { 44 | return this.wishlistService.findById(wishlistId, key); 45 | } 46 | 47 | @PutMapping(produces = "application/json", consumes = "application/json") 48 | public Mono update(@RequestBody Wishlist wishlist) { 49 | return this.wishlistService.save(wishlist); 50 | } 51 | 52 | @DeleteMapping(path = "/{wishlistId}", produces = "application/json") 53 | public Mono delete( 54 | @PathVariable("wishlistId") String wishlistId, 55 | @RequestParam(name = "key", defaultValue = "wishlist") String key) { 56 | return this.wishlistService.deleteById(wishlistId, key); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /demos/cosmos-db/demo/src/main/java/com/example/demo/dao/CustomerRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.dao; 2 | 3 | import com.example.demo.model.Customer; 4 | import com.azure.spring.data.cosmos.repository.ReactiveCosmosRepository; 5 | import com.azure.cosmos.models.PartitionKey; 6 | import org.springframework.stereotype.Repository; 7 | import reactor.core.publisher.*; 8 | 9 | @Repository 10 | public interface CustomerRepository extends ReactiveCosmosRepository { 11 | Mono deleteById(String customertId, PartitionKey key); 12 | 13 | Flux findAll(PartitionKey key); 14 | 15 | Mono findById(String customerId, PartitionKey key); 16 | 17 | Mono save(Customer customer); 18 | } 19 | -------------------------------------------------------------------------------- /demos/cosmos-db/demo/src/main/java/com/example/demo/dao/ManufacturerRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.dao; 2 | 3 | import com.example.demo.model.Manufacturer; 4 | import com.azure.spring.data.cosmos.repository.ReactiveCosmosRepository; 5 | import com.azure.cosmos.models.PartitionKey; 6 | import org.springframework.stereotype.Repository; 7 | import reactor.core.publisher.*; 8 | 9 | @Repository 10 | public interface ManufacturerRepository extends ReactiveCosmosRepository { 11 | Mono deleteById(String manufacturerId, PartitionKey key); 12 | 13 | Flux findAll(PartitionKey key); 14 | 15 | Mono findById(String manufactuerId, PartitionKey key); 16 | 17 | Mono save(Manufacturer manufacturer); 18 | } 19 | -------------------------------------------------------------------------------- /demos/cosmos-db/demo/src/main/java/com/example/demo/dao/ProductRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.dao; 2 | 3 | import com.example.demo.model.Product; 4 | import com.azure.spring.data.cosmos.repository.Query; 5 | import com.azure.spring.data.cosmos.repository.ReactiveCosmosRepository; 6 | import com.azure.cosmos.models.PartitionKey; 7 | import org.springframework.stereotype.Repository; 8 | import reactor.core.publisher.*; 9 | 10 | @Repository 11 | public interface ProductRepository extends ReactiveCosmosRepository { 12 | Mono deleteById(String productId, PartitionKey key); 13 | 14 | Flux findAll(PartitionKey key); 15 | 16 | Mono findById(String productId, PartitionKey key); 17 | 18 | Mono save(Product product); 19 | 20 | // Note: UPDATE isn't supported. This is here to quiet the compiler. 21 | @Query("UPDATE c SET c.msrp = @msrp WHERE c.Id=@id AND c.documentType=@documentType") 22 | void saveMsrp(Product product); 23 | } 24 | -------------------------------------------------------------------------------- /demos/cosmos-db/demo/src/main/java/com/example/demo/dao/WishlistRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.dao; 2 | 3 | import com.example.demo.model.Wishlist; 4 | import com.azure.spring.data.cosmos.repository.Query; 5 | import com.azure.spring.data.cosmos.repository.ReactiveCosmosRepository; 6 | import com.azure.cosmos.models.PartitionKey; 7 | 8 | import org.springframework.data.repository.query.Param; 9 | import org.springframework.stereotype.Repository; 10 | import reactor.core.publisher.*; 11 | 12 | @Repository 13 | public interface WishlistRepository extends ReactiveCosmosRepository { 14 | Mono deleteById(String wishlistId, PartitionKey key); 15 | 16 | Flux findAll(PartitionKey key); 17 | 18 | @Query("SELECT * FROM c WHERE c.customerId = @customerId AND c.documentType = 'wishlist'") 19 | Flux findByCustomerId(@Param("customerId") String customerId); 20 | 21 | @Query("SELECT * FROM c WHERE ARRAY_CONTAINS(c.productIds, @productId)") 22 | Flux findByProductId(@Param("productId") String productId); 23 | 24 | Mono findById(String wishlistId, PartitionKey key); 25 | 26 | Mono save(Wishlist wishlist); 27 | } 28 | -------------------------------------------------------------------------------- /demos/cosmos-db/demo/src/main/java/com/example/demo/model/BaseModel.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.model; 2 | 3 | import java.util.UUID; 4 | 5 | import com.azure.spring.data.cosmos.core.mapping.Container; 6 | import com.azure.spring.data.cosmos.core.mapping.PartitionKey; 7 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 8 | import com.fasterxml.jackson.annotation.JsonSubTypes; 9 | import com.fasterxml.jackson.annotation.JsonTypeInfo; 10 | import com.fasterxml.jackson.annotation.JsonTypeInfo.As; 11 | 12 | import org.springframework.data.annotation.Id; 13 | 14 | import lombok.Getter; 15 | import lombok.NoArgsConstructor; 16 | import lombok.Setter; 17 | 18 | @JsonIgnoreProperties(ignoreUnknown = true) 19 | @Container(containerName = "pet-supplies") 20 | @Getter @Setter @NoArgsConstructor 21 | @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = As.EXISTING_PROPERTY, property = "documentType") 22 | @JsonSubTypes({ 23 | @JsonSubTypes.Type(value = Customer.class, name="customer"), 24 | @JsonSubTypes.Type(value = Manufacturer.class, name="manufacturer"), 25 | @JsonSubTypes.Type(value = Product.class, name="product"), 26 | @JsonSubTypes.Type(value = Wishlist.class, name="wishlist") 27 | }) 28 | public class BaseModel { 29 | @Id 30 | protected String id = UUID.randomUUID().toString(); 31 | @PartitionKey 32 | protected String documentType = "unknown"; 33 | } 34 | -------------------------------------------------------------------------------- /demos/cosmos-db/demo/src/main/java/com/example/demo/model/Customer.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonTypeName; 4 | 5 | import lombok.*; 6 | 7 | @Getter @Setter 8 | @JsonTypeName("customer") 9 | public class Customer extends BaseModel { 10 | 11 | private String firstName; 12 | private String lastName; 13 | private String email; 14 | 15 | public Customer() { 16 | this.documentType = "customer"; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /demos/cosmos-db/demo/src/main/java/com/example/demo/model/Manufacturer.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.model; 2 | 3 | 4 | import com.fasterxml.jackson.annotation.JsonTypeName; 5 | 6 | import lombok.*; 7 | 8 | @Getter @Setter 9 | @JsonTypeName("manufacturer") 10 | public class Manufacturer extends BaseModel { 11 | 12 | private String name; 13 | 14 | public Manufacturer() { 15 | this.documentType = "manufacturer"; 16 | } 17 | 18 | } 19 | 20 | -------------------------------------------------------------------------------- /demos/cosmos-db/demo/src/main/java/com/example/demo/model/Product.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonTypeName; 4 | 5 | import lombok.*; 6 | 7 | @Getter @Setter 8 | @JsonTypeName("product") 9 | public class Product extends BaseModel { 10 | 11 | private String type; 12 | private String name; 13 | private String description; 14 | private String manufacturerId; 15 | private Double msrp; 16 | 17 | public Product() { 18 | this.documentType = "product"; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /demos/cosmos-db/demo/src/main/java/com/example/demo/model/Wishlist.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.model; 2 | 3 | import lombok.*; 4 | import java.util.Set; 5 | import javax.validation.constraints.NotBlank; 6 | 7 | import com.fasterxml.jackson.annotation.JsonTypeName; 8 | 9 | @Getter @Setter 10 | @JsonTypeName("wishlist") 11 | public class Wishlist extends BaseModel { 12 | 13 | @NotBlank 14 | private String customerId; 15 | private String customerEmail; 16 | private Set productIds; 17 | private Set products; 18 | 19 | public Wishlist() { 20 | this.documentType = "wishlist"; 21 | } 22 | 23 | public void addProduct(Product product) { 24 | this.productIds.add(product.getId()); 25 | this.products.removeIf(p -> p.getId() == product.getId()); 26 | this.products.add(product); 27 | } 28 | 29 | public void removeProduct(String productId) { 30 | this.productIds.remove(productId); 31 | this.products.removeIf(p -> p.getId() == productId); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /demos/cosmos-db/demo/src/main/java/com/example/demo/service/BulkExecutorService.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.service; 2 | 3 | import java.util.List; 4 | 5 | import com.example.demo.model.BaseModel; 6 | import com.fasterxml.jackson.core.JsonProcessingException; 7 | import com.fasterxml.jackson.databind.ObjectMapper; 8 | 9 | import reactor.core.publisher.Flux; 10 | 11 | import org.springframework.stereotype.Component; 12 | import org.slf4j.Logger; 13 | import org.slf4j.LoggerFactory; 14 | 15 | import com.azure.cosmos.CosmosAsyncClient; 16 | import com.azure.cosmos.CosmosAsyncContainer; 17 | import com.azure.cosmos.CosmosAsyncDatabase; 18 | import com.azure.cosmos.models.*; 19 | 20 | @Component 21 | public class BulkExecutorService { 22 | 23 | private static final Logger LOGGER = LoggerFactory.getLogger(BulkExecutorService.class); 24 | 25 | CosmosAsyncClient client; 26 | CosmosAsyncDatabase database; 27 | CosmosAsyncContainer container; 28 | ObjectMapper mapper; 29 | 30 | //favouring constructor dependency injection 31 | public BulkExecutorService(CosmosAsyncClient client, CosmosAsyncDatabase database, CosmosAsyncContainer container, ObjectMapper mapper){ 32 | this.client = client; 33 | this.database = database; 34 | this.container = container; 35 | this.mapper = mapper; 36 | } 37 | 38 | public CosmosBulkItemResponse bulkDelete(List deleteItems) { 39 | Flux docs = Flux.fromIterable(deleteItems); 40 | Flux cosmosItemOperations = docs.map( 41 | document -> CosmosBulkOperations 42 | .getDeleteItemOperation(document.getId(), new PartitionKey(document.getDocumentType()))); 43 | return container.executeBulkOperations(cosmosItemOperations).blockLast().getResponse(); 44 | } 45 | 46 | private String serialize(BaseModel model) { 47 | String rawJson = null; 48 | try { 49 | rawJson = mapper.writeValueAsString(model); 50 | } catch (JsonProcessingException ex) { 51 | LOGGER.error("Error serializing", ex); 52 | } 53 | LOGGER.info(rawJson); 54 | return rawJson; 55 | } 56 | 57 | public CosmosBulkItemResponse bulkImport(List documents) { 58 | Flux docs = Flux.fromIterable(documents); 59 | Flux cosmosItemOperations = docs.map( 60 | document -> CosmosBulkOperations.getUpsertItemOperation(document, new PartitionKey(document.getDocumentType()))); 61 | return container.executeBulkOperations(cosmosItemOperations).blockLast().getResponse(); 62 | } 63 | 64 | public CosmosBulkItemResponse bulkUpdate(List updateItems) { 65 | Flux docs = Flux.fromIterable(updateItems); 66 | Flux cosmosItemOperations = docs.map( 67 | document -> CosmosBulkOperations.getUpsertItemOperation(document, new PartitionKey(document.getDocumentType()))); 68 | return container.executeBulkOperations(cosmosItemOperations).blockLast().getResponse(); 69 | } 70 | } -------------------------------------------------------------------------------- /demos/cosmos-db/demo/src/main/java/com/example/demo/service/ChangeFeedService.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.service; 2 | 3 | import java.util.List; 4 | 5 | import javax.annotation.PostConstruct; 6 | import com.azure.cosmos.ChangeFeedProcessor; 7 | import com.azure.cosmos.ChangeFeedProcessorBuilder; 8 | import com.example.demo.model.Product; 9 | import com.fasterxml.jackson.databind.JsonNode; 10 | import com.fasterxml.jackson.databind.ObjectMapper; 11 | 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.stereotype.Component; 14 | import reactor.core.publisher.Flux; 15 | 16 | @Component 17 | public class ChangeFeedService { 18 | 19 | @Autowired 20 | private ChangeFeedProcessorBuilder cfProcessorBuilder; 21 | private ChangeFeedProcessor cFeedProcessor; 22 | public ChangedProductSink productSink = new ChangedProductSink(); 23 | //Subscribe to this to receive changed products 24 | public Flux changedProducts; 25 | 26 | @PostConstruct 27 | public void init() { 28 | cFeedProcessor = cfProcessorBuilder 29 | .handleChanges( 30 | (List changes) -> { handleChanges(changes); }) 31 | .buildChangeFeedProcessor(); 32 | cFeedProcessor.start().subscribe(System.out::println); 33 | changedProducts = Flux.create(productSink); 34 | changedProducts.subscribe(System.out::println); 35 | } 36 | 37 | public void handleChanges(List changes) { 38 | ObjectMapper objectMapper = new ObjectMapper(); 39 | changes.forEach(node -> { 40 | try { 41 | // Consumer's accept doesn't fire until a client starts listening 42 | if (productSink == null) { 43 | return; 44 | } 45 | // Change feed documents come in as json nodes from creates/updates to any document in the container 46 | if (node.get("documentType").asText().equals("product")) { 47 | productSink.next(objectMapper.readValue(node.toString(), Product.class)); 48 | } 49 | } catch (Exception ex) { 50 | System.out.println(ex); 51 | } 52 | }); 53 | 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /demos/cosmos-db/demo/src/main/java/com/example/demo/service/ChangedProductSink.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.service; 2 | 3 | import java.util.function.Consumer; 4 | import com.example.demo.model.Product; 5 | import reactor.core.publisher.FluxSink; 6 | 7 | public class ChangedProductSink implements Consumer> { 8 | private FluxSink sink; 9 | 10 | @Override 11 | public void accept(FluxSink productFluxSink) { 12 | this.sink = productFluxSink; 13 | } 14 | 15 | public void next(Product product) { 16 | this.sink.next(product); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /demos/cosmos-db/demo/src/main/java/com/example/demo/service/CustomerService.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.service; 2 | 3 | import com.azure.cosmos.models.PartitionKey; 4 | import com.example.demo.dao.CustomerRepository; 5 | import com.example.demo.model.Customer; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Component; 8 | import javax.annotation.PostConstruct; 9 | import reactor.core.publisher.Flux; 10 | import reactor.core.publisher.Mono; 11 | 12 | @Component 13 | public class CustomerService { 14 | 15 | @Autowired 16 | private CustomerRepository repository; 17 | 18 | @Autowired 19 | private WishlistService wishlistService; 20 | 21 | @PostConstruct 22 | public void init() { 23 | wishlistService.setCustomerService(this); 24 | } 25 | 26 | public Flux findAll(String partitionKey) { 27 | PartitionKey key = new PartitionKey(partitionKey); 28 | return this.repository.findAll(key); 29 | } 30 | 31 | public Mono findById(String customer, String key) { 32 | PartitionKey partitionKey = new PartitionKey(key); 33 | return this.repository.findById(customer, partitionKey); 34 | } 35 | 36 | public Mono deleteById(String customerId, String key) { 37 | return this.repository.findById(customerId) 38 | .flatMap(customer -> 39 | this.repository.delete(customer) 40 | .then(this.wishlistService.deleteByCustomerId(customerId)) 41 | .thenReturn(true)) 42 | .defaultIfEmpty(false); 43 | } 44 | 45 | public Mono save(Customer customer) { 46 | return this.repository.save(customer); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /demos/cosmos-db/demo/src/main/java/com/example/demo/service/ManufacturerService.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.service; 2 | 3 | import com.azure.cosmos.models.PartitionKey; 4 | import com.example.demo.dao.ManufacturerRepository; 5 | import com.example.demo.model.Manufacturer; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Component; 8 | import reactor.core.publisher.Flux; 9 | import reactor.core.publisher.Mono; 10 | 11 | @Component 12 | public class ManufacturerService { 13 | 14 | @Autowired 15 | private ManufacturerRepository repository; 16 | 17 | public Flux findAll(String key) { 18 | PartitionKey partitionKey = new PartitionKey(key); 19 | return this.repository.findAll(partitionKey); 20 | } 21 | 22 | public Mono findById(String manufacturerId, String key) { 23 | PartitionKey partitionKey = new PartitionKey(key); 24 | return this.repository.findById(manufacturerId, partitionKey); 25 | } 26 | 27 | public Mono deleteById(String customerId, String key) { 28 | PartitionKey partitionKey = new PartitionKey(key); 29 | return this.repository.findById(customerId, partitionKey) 30 | .flatMap(customer -> 31 | this.repository.delete(customer) 32 | .then(Mono.just(true)) 33 | ).defaultIfEmpty(false); 34 | } 35 | 36 | public Mono save(Manufacturer product) { 37 | return this.repository.save(product); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /demos/cosmos-db/demo/src/main/java/com/example/demo/service/ProductService.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.service; 2 | 3 | import com.azure.cosmos.CosmosClient; 4 | import com.azure.cosmos.CosmosContainer; 5 | import com.azure.cosmos.CosmosDatabase; 6 | import com.azure.cosmos.models.CosmosPatchItemRequestOptions; 7 | import com.azure.cosmos.models.CosmosPatchOperations; 8 | import com.azure.cosmos.models.PartitionKey; 9 | import com.example.demo.config.CosmosConfiguration; 10 | import com.example.demo.dao.ProductRepository; 11 | import com.example.demo.model.Product; 12 | 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.beans.factory.annotation.Value; 15 | import org.springframework.stereotype.Component; 16 | import javax.annotation.PostConstruct; 17 | 18 | import lombok.extern.slf4j.Slf4j; 19 | import reactor.core.publisher.Flux; 20 | import reactor.core.publisher.Mono; 21 | 22 | @Component 23 | @Slf4j 24 | public class ProductService { 25 | 26 | @Autowired 27 | private ProductRepository repository; 28 | 29 | @Autowired 30 | private WishlistService wishlistService; 31 | 32 | private CosmosConfiguration cosmosConfig; 33 | 34 | @Value("${azure.cosmos.database}") 35 | private String dbName; 36 | 37 | @Value("${azure.cosmos.feed-container}") 38 | private String containerName; 39 | 40 | @PostConstruct 41 | public void init() { 42 | wishlistService.setProductService(this); 43 | } 44 | 45 | public Flux findAll(String key) { 46 | PartitionKey partitionKey = new PartitionKey(key); 47 | return this.repository.findAll(partitionKey); 48 | } 49 | 50 | public Mono findById(String productId, String key) { 51 | PartitionKey partitionKey = new PartitionKey(key); 52 | return this.repository.findById(productId, partitionKey); 53 | } 54 | 55 | public Mono deleteById(String productId, String key) { 56 | PartitionKey partitionKey = new PartitionKey(key); 57 | return this.repository.findById(productId, partitionKey) 58 | .flatMap(product -> this.repository.delete(product)) 59 | .thenMany(this.wishlistService.findByProductId(productId)) 60 | .flatMap(wishlist -> { 61 | log.info("removing product {}", productId); 62 | log.info("products in wishlist {}", wishlist.getProducts()); 63 | wishlist.removeProduct(productId); 64 | return this.wishlistService.save(wishlist); 65 | }) 66 | .then(Mono.just(true)); 67 | } 68 | 69 | public Mono save(Product product) { 70 | return this.wishlistService.findByProductId(product.getId()) 71 | .flatMap(wishlist -> { 72 | log.info("Updating wishlist with product {}", product.getManufacturerId()); 73 | wishlist.addProduct(product); 74 | return this.wishlistService.save(wishlist); 75 | }) 76 | .then(repository.save(product)); 77 | 78 | } 79 | 80 | // Used to show partial document updates 81 | // This is using the Azure Cosmos DB Java SDK v4 82 | public void saveMsrp(Product product){ 83 | CosmosClient client = cosmosConfig.getCosmosClientBuilder().buildClient(); 84 | CosmosDatabase database = client.getDatabase(dbName); 85 | CosmosContainer container = database.getContainer(containerName); 86 | CosmosPatchOperations cosmosPatchOperations = CosmosPatchOperations.create(); 87 | cosmosPatchOperations.replace("/msrp", product.getMsrp()); 88 | CosmosPatchItemRequestOptions options = new CosmosPatchItemRequestOptions(); 89 | try { 90 | container.patchItem(product.getId(), new PartitionKey(product.getDocumentType()), cosmosPatchOperations, options, Product.class); 91 | log.info("Updating the price for product {}", product.getName()); 92 | } catch (Exception e){ 93 | log.error("Failed the partial update for product {}", product.getName()); 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /demos/cosmos-db/demo/src/main/java/com/example/demo/service/WishlistService.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.service; 2 | 3 | import java.util.stream.Collectors; 4 | 5 | import com.azure.cosmos.implementation.NotFoundException; 6 | import com.azure.cosmos.models.PartitionKey; 7 | import com.example.demo.dao.WishlistRepository; 8 | import com.example.demo.model.Customer; 9 | import com.example.demo.model.Wishlist; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.stereotype.Component; 12 | 13 | import reactor.core.publisher.Flux; 14 | import reactor.core.publisher.Mono; 15 | 16 | @Component 17 | public class WishlistService { 18 | 19 | @Autowired 20 | private WishlistRepository repository; 21 | 22 | private CustomerService customerService; 23 | 24 | private ProductService productService; 25 | 26 | public void setCustomerService(CustomerService customerService) { 27 | this.customerService = customerService; 28 | } 29 | 30 | public void setProductService(ProductService productService){ 31 | this.productService = productService; 32 | } 33 | 34 | public Flux findAll(String key) { 35 | PartitionKey partitionKey = new PartitionKey(key); 36 | return this.repository.findAll(partitionKey); 37 | } 38 | 39 | public Mono findById(String wishlistId, String key) { 40 | PartitionKey partitionKey = new PartitionKey(key); 41 | return this.repository.findById(wishlistId, partitionKey); 42 | } 43 | 44 | public Flux findByProductId(String productId) { 45 | return this.repository.findByProductId(productId); 46 | } 47 | 48 | public Mono deleteById(String wishlistId, String key) { 49 | PartitionKey partitionKey = new PartitionKey(key); 50 | return this.repository.findById(wishlistId, partitionKey) 51 | .flatMap(wishlist -> 52 | this.repository.delete(wishlist) 53 | .then(Mono.just(true)) 54 | ).defaultIfEmpty(false); 55 | } 56 | 57 | public Mono deleteByCustomerId(String customerId) { 58 | return this.repository.findByCustomerId(customerId) 59 | .flatMap( 60 | wishlist -> 61 | this.deleteById(wishlist.getId(), "wishlist") 62 | ) 63 | .all(deleted -> deleted == true); 64 | } 65 | 66 | public Mono save(Wishlist wishlist) { 67 | Flux productIds = Flux.fromIterable(wishlist.getProductIds()); 68 | Mono findCustomer = this.customerService.findById(wishlist.getCustomerId(), "customer"); 69 | return findCustomer 70 | .switchIfEmpty( 71 | Mono.error( 72 | new NotFoundException( 73 | String.format("Customer id %s not found", wishlist.getCustomerId()) 74 | ) 75 | ) 76 | ) 77 | .thenMany(productIds) 78 | .flatMap(productId -> { 79 | return this.productService.findById(productId, "product") 80 | .switchIfEmpty( 81 | Mono.error( 82 | new NotFoundException( 83 | String.format("Product id %s not found", productId) 84 | ) 85 | ) 86 | ); 87 | }) 88 | .collect(Collectors.toSet()) 89 | .flatMap(products -> { 90 | wishlist.setProducts(products); 91 | return this.repository.save(wishlist); 92 | }); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /demos/cosmos-db/demo/src/main/resources/application-default.properties: -------------------------------------------------------------------------------- 1 | azure.cosmos.uri=${AZURE_COSMOS_URI} 2 | azure.cosmos.key=${AZURE_COSMOS_KEY} 3 | azure.cosmos.database=pet-supplies 4 | 5 | #values for change feed processor 6 | azure.cosmos.feed-container=pet-supplies 7 | azure.cosmos.lease-container=lease 8 | 9 | # values for bulk executor 10 | azure.cosmos.collection=pet-supplies 11 | azure.cosmos.partitionKey=documentType 12 | azure.cosmos.collectionThroughput = 100000; 13 | 14 | spring.cloud.config.import-check.enabled=false 15 | spring.cloud.discovery.enabled=false 16 | spring.mvc.async.request-timeout=-1 -------------------------------------------------------------------------------- /demos/cosmos-db/demo/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/demos/cosmos-db/demo/src/main/resources/application.properties -------------------------------------------------------------------------------- /demos/cosmos-db/demo/src/main/resources/static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Contoso Pet Supplies 8 | 9 | 10 | 11 |

Contoso Pet Supplies

12 |

These are the API endpoints:

13 | 21 |

These are best tested with this Postman collection.

22 | 23 | -------------------------------------------------------------------------------- /demos/cosmos-db/demo/src/test/java/com/example/demo/DemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class DemoApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /demos/cosmos-function/azure-cosmos-db-function-demo-from-maven/function/host.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0", 3 | "extensionBundle": { 4 | "id": "Microsoft.Azure.Functions.ExtensionBundle", 5 | "version": "[2.*, 3.0.0)" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /demos/cosmos-function/azure-cosmos-db-function-demo-from-maven/function/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | com 6 | function 7 | 1.0-SNAPSHOT 8 | jar 9 | 10 | Azure Java Functions 11 | 12 | 13 | UTF-8 14 | 1.8 15 | 1.16.0 16 | 1.4.2 17 | cosmosChangeFeedProcessorFunction 18 | 19 | 20 | 21 | 22 | com.microsoft.azure.functions 23 | azure-functions-java-library 24 | ${azure.functions.java.library.version} 25 | 26 | 27 | 28 | 29 | org.junit.jupiter 30 | junit-jupiter 31 | 5.4.2 32 | test 33 | 34 | 35 | 36 | org.mockito 37 | mockito-core 38 | 2.23.4 39 | test 40 | 41 | 42 | 43 | 44 | 45 | 46 | org.apache.maven.plugins 47 | maven-compiler-plugin 48 | 3.8.1 49 | 50 | ${java.version} 51 | ${java.version} 52 | ${project.build.sourceEncoding} 53 | 54 | 55 | 56 | com.microsoft.azure 57 | azure-functions-maven-plugin 58 | ${azure.functions.maven.plugin.version} 59 | 60 | 61 | ${functionAppName} 62 | 63 | pet-supplies-demo-rg 64 | 65 | java-functions-app-service-plan 66 | 67 | 68 | eastus 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | windows 78 | 8 79 | 80 | 81 | 82 | FUNCTIONS_EXTENSION_VERSION 83 | ~3 84 | 85 | 86 | AzureWebJobsStorage 87 | ${AZURE_WEBJOBS_STORAGE} 88 | 89 | 90 | AzureCosmosDBConnectionString 91 | ${AZURE_COSMOS_CONNECTION_STRING} 92 | 93 | 94 | AzureEventHubConnection 95 | ${AZURE_EVENT_HUB_CONNECTION} 96 | 97 | 98 | 99 | 100 | 101 | package-functions 102 | 103 | package 104 | 105 | 106 | 107 | 108 | 109 | 110 | maven-clean-plugin 111 | 3.1.0 112 | 113 | 114 | 115 | obj 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /demos/cosmos-function/azure-cosmos-db-function-demo-from-maven/function/src/main/java/com/Function.java: -------------------------------------------------------------------------------- 1 | package com; 2 | 3 | import com.microsoft.azure.functions.annotation.*; 4 | import com.microsoft.azure.functions.*; 5 | 6 | /** 7 | * Azure Functions with Cosmos DB trigger. 8 | */ 9 | public class Function { 10 | /** 11 | * This function will be invoked when there are inserts or updates in the specified database and collection. 12 | */ 13 | @FunctionName("CosmosDBChangeFeedMonitor") 14 | @EventHubOutput(name = "event", eventHubName = "pet-supplies-events", connection = "AzureEventHubConnection") 15 | public Object[] pushToEventGrid( 16 | @CosmosDBTrigger( 17 | name = "items", 18 | databaseName = "pet-supplies", 19 | collectionName = "pet-supplies", 20 | leaseCollectionName="lease", 21 | connectionStringSetting = "AzureCosmosDBConnectionString", 22 | createLeaseCollectionIfNotExists = true 23 | ) 24 | Object[] items, 25 | final ExecutionContext context 26 | ) { 27 | context.getLogger().info("Java Cosmos DB trigger function executed."); 28 | context.getLogger().info("Documents count: " + items.length); 29 | return items; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /demos/hello-world-keyvault/demo/.mvn/wrapper/MavenWrapperDownloader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2007-present the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import java.net.*; 17 | import java.io.*; 18 | import java.nio.channels.*; 19 | import java.util.Properties; 20 | 21 | public class MavenWrapperDownloader { 22 | 23 | private static final String WRAPPER_VERSION = "0.5.6"; 24 | /** 25 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. 26 | */ 27 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" 28 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; 29 | 30 | /** 31 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to 32 | * use instead of the default one. 33 | */ 34 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH = 35 | ".mvn/wrapper/maven-wrapper.properties"; 36 | 37 | /** 38 | * Path where the maven-wrapper.jar will be saved to. 39 | */ 40 | private static final String MAVEN_WRAPPER_JAR_PATH = 41 | ".mvn/wrapper/maven-wrapper.jar"; 42 | 43 | /** 44 | * Name of the property which should be used to override the default download url for the wrapper. 45 | */ 46 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; 47 | 48 | public static void main(String args[]) { 49 | System.out.println("- Downloader started"); 50 | File baseDirectory = new File(args[0]); 51 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); 52 | 53 | // If the maven-wrapper.properties exists, read it and check if it contains a custom 54 | // wrapperUrl parameter. 55 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); 56 | String url = DEFAULT_DOWNLOAD_URL; 57 | if(mavenWrapperPropertyFile.exists()) { 58 | FileInputStream mavenWrapperPropertyFileInputStream = null; 59 | try { 60 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); 61 | Properties mavenWrapperProperties = new Properties(); 62 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); 63 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); 64 | } catch (IOException e) { 65 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); 66 | } finally { 67 | try { 68 | if(mavenWrapperPropertyFileInputStream != null) { 69 | mavenWrapperPropertyFileInputStream.close(); 70 | } 71 | } catch (IOException e) { 72 | // Ignore ... 73 | } 74 | } 75 | } 76 | System.out.println("- Downloading from: " + url); 77 | 78 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); 79 | if(!outputFile.getParentFile().exists()) { 80 | if(!outputFile.getParentFile().mkdirs()) { 81 | System.out.println( 82 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); 83 | } 84 | } 85 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); 86 | try { 87 | downloadFileFromURL(url, outputFile); 88 | System.out.println("Done"); 89 | System.exit(0); 90 | } catch (Throwable e) { 91 | System.out.println("- Error downloading"); 92 | e.printStackTrace(); 93 | System.exit(1); 94 | } 95 | } 96 | 97 | private static void downloadFileFromURL(String urlString, File destination) throws Exception { 98 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { 99 | String username = System.getenv("MVNW_USERNAME"); 100 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); 101 | Authenticator.setDefault(new Authenticator() { 102 | @Override 103 | protected PasswordAuthentication getPasswordAuthentication() { 104 | return new PasswordAuthentication(username, password); 105 | } 106 | }); 107 | } 108 | URL website = new URL(urlString); 109 | ReadableByteChannel rbc; 110 | rbc = Channels.newChannel(website.openStream()); 111 | FileOutputStream fos = new FileOutputStream(destination); 112 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); 113 | fos.close(); 114 | rbc.close(); 115 | } 116 | 117 | } 118 | -------------------------------------------------------------------------------- /demos/hello-world-keyvault/demo/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.3/apache-maven-3.8.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /demos/hello-world-keyvault/demo/mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM https://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM set title of command window 39 | title %0 40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' 41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 42 | 43 | @REM set %HOME% to equivalent of $HOME 44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 45 | 46 | @REM Execute a user defined script before this one 47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 51 | :skipRcPre 52 | 53 | @setlocal 54 | 55 | set ERROR_CODE=0 56 | 57 | @REM To isolate internal variables from possible post scripts, we use another setlocal 58 | @setlocal 59 | 60 | @REM ==== START VALIDATION ==== 61 | if not "%JAVA_HOME%" == "" goto OkJHome 62 | 63 | echo. 64 | echo Error: JAVA_HOME not found in your environment. >&2 65 | echo Please set the JAVA_HOME variable in your environment to match the >&2 66 | echo location of your Java installation. >&2 67 | echo. 68 | goto error 69 | 70 | :OkJHome 71 | if exist "%JAVA_HOME%\bin\java.exe" goto init 72 | 73 | echo. 74 | echo Error: JAVA_HOME is set to an invalid directory. >&2 75 | echo JAVA_HOME = "%JAVA_HOME%" >&2 76 | echo Please set the JAVA_HOME variable in your environment to match the >&2 77 | echo location of your Java installation. >&2 78 | echo. 79 | goto error 80 | 81 | @REM ==== END VALIDATION ==== 82 | 83 | :init 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 122 | 123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 124 | 125 | FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( 126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B 127 | ) 128 | 129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data. 131 | if exist %WRAPPER_JAR% ( 132 | if "%MVNW_VERBOSE%" == "true" ( 133 | echo Found %WRAPPER_JAR% 134 | ) 135 | ) else ( 136 | if not "%MVNW_REPOURL%" == "" ( 137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 138 | ) 139 | if "%MVNW_VERBOSE%" == "true" ( 140 | echo Couldn't find %WRAPPER_JAR%, downloading it ... 141 | echo Downloading from: %DOWNLOAD_URL% 142 | ) 143 | 144 | powershell -Command "&{"^ 145 | "$webclient = new-object System.Net.WebClient;"^ 146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ 147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ 148 | "}"^ 149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ 150 | "}" 151 | if "%MVNW_VERBOSE%" == "true" ( 152 | echo Finished downloading %WRAPPER_JAR% 153 | ) 154 | ) 155 | @REM End of extension 156 | 157 | @REM Provide a "standardized" way to retrieve the CLI args that will 158 | @REM work with both Windows and non-Windows executions. 159 | set MAVEN_CMD_LINE_ARGS=%* 160 | 161 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 162 | if ERRORLEVEL 1 goto error 163 | goto end 164 | 165 | :error 166 | set ERROR_CODE=1 167 | 168 | :end 169 | @endlocal & set ERROR_CODE=%ERROR_CODE% 170 | 171 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 172 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 173 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 174 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 175 | :skipRcPost 176 | 177 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 178 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 179 | 180 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 181 | 182 | exit /B %ERROR_CODE% 183 | -------------------------------------------------------------------------------- /demos/hello-world-keyvault/demo/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.5.8 9 | 10 | 11 | 12 | com.example 13 | demo 14 | 0.0.1-SNAPSHOT 15 | demo 16 | Demo project for Spring Boot 17 | 18 | 11 19 | 3.10.0 20 | 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-starter-web 25 | 26 | 27 | com.azure.spring 28 | azure-spring-boot-starter-keyvault-secrets 29 | 30 | 31 | com.azure 32 | azure-identity 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-starter-test 37 | test 38 | 39 | 40 | 41 | 42 | 43 | com.azure.spring 44 | azure-spring-boot-bom 45 | ${azure.version} 46 | pom 47 | import 48 | 49 | 50 | 51 | 52 | 53 | 54 | org.springframework.boot 55 | spring-boot-maven-plugin 56 | 57 | 58 | com.microsoft.azure 59 | azure-webapp-maven-plugin 60 | 2.2.3 61 | 62 | v2 63 | java-keyvault-demo-rg 64 | java-keyvault-demo-asp 65 | java-keyvault-app 66 | eastus 67 | 68 | Linux 69 | Java 11 70 | Java SE 71 | 72 | 73 | 74 | 75 | ${project.basedir}/target 76 | 77 | *.jar 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /demos/hello-world-keyvault/demo/src/main/java/com/example/demo/DemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class DemoApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(DemoApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /demos/hello-world-keyvault/demo/src/main/java/com/example/demo/KeyvaultDemoController.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.springframework.web.bind.annotation.RequestMapping; 4 | import org.springframework.web.bind.annotation.RestController; 5 | 6 | import com.azure.identity.DefaultAzureCredentialBuilder; 7 | 8 | import com.azure.security.keyvault.secrets.SecretClient; 9 | import com.azure.security.keyvault.secrets.SecretClientBuilder; 10 | import com.azure.security.keyvault.secrets.models.KeyVaultSecret; 11 | 12 | @RestController 13 | public class KeyvaultDemoController 14 | { 15 | @RequestMapping("/") 16 | public String getKeyvaultValue() 17 | { 18 | return getStoredValue("keyName"); 19 | } 20 | 21 | private String getStoredValue(String keyName){ 22 | String keyVaultName = System.getenv("KEY_VAULT_NAME"); 23 | String keyVaultUri = "https://" + keyVaultName + ".vault.azure.net"; 24 | SecretClient secretClient = new SecretClientBuilder() 25 | .vaultUrl(keyVaultUri) 26 | .credential(new DefaultAzureCredentialBuilder().build()) 27 | .buildClient(); 28 | KeyVaultSecret storedSecret = secretClient.getSecret("keyName"); 29 | return storedSecret.getValue(); 30 | } 31 | } -------------------------------------------------------------------------------- /demos/hello-world-keyvault/demo/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/demos/hello-world-keyvault/demo/src/main/resources/application.properties -------------------------------------------------------------------------------- /demos/hello-world-keyvault/demo/src/test/java/com/example/demo/DemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class DemoApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /demos/host.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0", 3 | "logging": { 4 | "applicationInsights": { 5 | "samplingSettings": { 6 | "isEnabled": true, 7 | "excludedTypes": "Request" 8 | } 9 | } 10 | }, 11 | "extensionBundle": { 12 | "id": "Microsoft.Azure.Functions.ExtensionBundle", 13 | "version": "[2.*, 3.0.0)" 14 | }, 15 | "customHandler": { 16 | "description": { 17 | "defaultExecutablePath": "", 18 | "workingDirectory": "", 19 | "arguments": [] 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/ruby,jekyll 3 | 4 | ### Jekyll ### 5 | _site/ 6 | .sass-cache/ 7 | .jekyll-metadata 8 | 9 | ### Ruby ### 10 | Gemfile 11 | Gemfile.lock 12 | *.gem 13 | *.rbc 14 | /.config 15 | /coverage/ 16 | /InstalledFiles 17 | /pkg/ 18 | /spec/reports/ 19 | /spec/examples.txt 20 | /test/tmp/ 21 | /test/version_tmp/ 22 | /tmp/ 23 | 24 | # Used by dotenv library to load environment variables. 25 | # .env 26 | 27 | ## Specific to RubyMotion: 28 | .dat* 29 | .repl_history 30 | build/ 31 | *.bridgesupport 32 | build-iPhoneOS/ 33 | build-iPhoneSimulator/ 34 | 35 | ## Specific to RubyMotion (use of CocoaPods): 36 | # 37 | # We recommend against adding the Pods directory to your .gitignore. However 38 | # you should judge for yourself, the pros and cons are mentioned at: 39 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 40 | # 41 | # vendor/Pods/ 42 | 43 | ## Documentation cache and generated files: 44 | /.yardoc/ 45 | /_yardoc/ 46 | /doc/ 47 | /rdoc/ 48 | 49 | ## Environment normalization: 50 | /.bundle/ 51 | /vendor/bundle 52 | /lib/bundler/man/ 53 | 54 | # for a library or gem, you might want to ignore these files since the code is 55 | # intended to run in multiple environments; otherwise, check them in: 56 | # Gemfile.lock 57 | # .ruby-version 58 | # .ruby-gemset 59 | 60 | # unless supporting rvm < 1.11.0 or doing something fancy, ignore this: 61 | .rvmrc 62 | 63 | 64 | # End of https://www.gitignore.io/api/ruby,jekyll -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman 2 | title: | 3 | Cloud-Scale Data for Spring Developers 4 | description: | 5 | Java + Azure Cosmos DB + Azure Spring Apps + Azure Functions + Azure Cognitive Search + more! 6 | exclude: 7 | - .build/ 8 | plugins: 9 | - jekyll-sitemap 10 | - jekyll-mentions 11 | - jemoji 12 | - jekyll-relative-links 13 | markdown: kramdown 14 | kramdown: 15 | syntax_highlighter_opts: 16 | disable : true 17 | sass: 18 | style: compressed 19 | -------------------------------------------------------------------------------- /docs/_includes/footer.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/_includes/links.html: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /docs/_includes/navigation.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/_layouts/default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{ site.title }} - {{ page.title }} 8 | 9 | 10 | 11 | 12 | 13 | 14 | {{ content }} 15 | 16 | -------------------------------------------------------------------------------- /docs/_layouts/home.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 | 5 | 6 | {% include navigation.html %} 7 |
8 |
9 |

10 | {{site.description}} 11 |

12 | {% include links.html %} 13 |
14 |
15 |
16 |
17 |
18 | 20 |
21 | {{ content }} 22 |
23 |
24 |
25 |
26 | {% include footer.html %} 27 | 30 | 33 | 36 | 39 | 47 | -------------------------------------------------------------------------------- /docs/_layouts/page.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 | 5 | 6 | {% include navigation.html %} 7 |
8 |
9 |

{{page.title}}

10 |
11 |
12 |
13 |
14 | 40 |
41 | {{ content }} 42 |
43 | 46 |
47 |
48 | {% include footer.html %} 49 | 52 | 55 | 58 | 61 | 125 | -------------------------------------------------------------------------------- /docs/_sass/code.scss: -------------------------------------------------------------------------------- 1 | pre code { 2 | border: 0; 3 | padding: 0; 4 | display: block; 5 | } 6 | 7 | p code { 8 | font-size: 0.8rem; 9 | background-color: #ffffff; 10 | } 11 | 12 | code, 13 | pre { 14 | font-size: .875rem; 15 | background-color: #ffffff; 16 | } 17 | 18 | code { 19 | border-radius: 2px; 20 | border: 1px solid #d3d6db; 21 | display: inline-block; 22 | padding: 0 7px; 23 | } 24 | 25 | code.hljs { 26 | background-color: transparent !important; 27 | } 28 | 29 | pre { 30 | overflow: auto; 31 | padding: 16px; 32 | margin: 16px 0 0; 33 | direction: ltr; 34 | white-space: pre; 35 | word-spacing: normal; 36 | word-break: normal; 37 | word-wrap: normal; 38 | -moz-tab-size: 4; 39 | -o-tab-size: 4; 40 | tab-size: 4; 41 | -webkit-hyphens: none; 42 | -ms-hyphens: none; 43 | hyphens: none; 44 | -webkit-overflow-scrolling: touch; 45 | border: 1px solid #d3d6db; 46 | } 47 | 48 | .text-dark-primary { 49 | color: #243a5e; 50 | } -------------------------------------------------------------------------------- /docs/_sass/cosmos.scss: -------------------------------------------------------------------------------- 1 | nav.navbar-cosmos { 2 | background-color: #2f2f2f; 3 | border-color: #505050; 4 | } 5 | 6 | .cosmos-background { 7 | background-color: #243a5e; 8 | } 9 | 10 | article.home { 11 | padding-top: 15px; 12 | 13 | h1 { 14 | display: none; 15 | } 16 | } 17 | 18 | article.workshop { 19 | h1 { 20 | display: none; 21 | } 22 | } 23 | 24 | article { 25 | .btn-primary { 26 | border: #243a5e; 27 | background-color: #243a5e; 28 | color: #50e6ff; 29 | 30 | &:hover { 31 | background-color: #50e6ff; 32 | color: #243a5e; 33 | text-decoration: none; 34 | } 35 | 36 | &:before { 37 | content: "\01F782\00a0"; 38 | } 39 | } 40 | } 41 | 42 | .hero-container { 43 | padding-top: 15px; 44 | padding-bottom: 15px; 45 | } 46 | 47 | .hero-content { 48 | padding-left: 15px; 49 | padding-right: 15px; 50 | color: #FFFFFF; 51 | 52 | p { 53 | font-weight: $ms-font-weight-semibold; 54 | font-size: $ms-font-size-xl; 55 | line-height: $ms-font-size-xxl; 56 | } 57 | 58 | ul { 59 | li { 60 | margin: 10px 0 6px; 61 | font-weight: $ms-font-weight-semilight; 62 | font-size: $ms-font-size-l; 63 | line-height: $ms-font-size-xl; 64 | 65 | a { 66 | color: #50e6ff; 67 | text-decoration: underline; 68 | } 69 | } 70 | } 71 | 72 | &.extra-padding { 73 | padding-top: 35px; 74 | padding-bottom: 35px; 75 | } 76 | } 77 | 78 | .text-cosmos { 79 | color: #50e6ff; 80 | font-size: $ms-font-size-xl; 81 | line-height: 20px; 82 | float: left; 83 | height: 50px; 84 | padding: 15px 15px; 85 | background-color: transparent; 86 | background-image: url(../img/logo.svg); 87 | padding-left: 50px; 88 | background-repeat: no-repeat; 89 | background-size: 45px; 90 | background-position: 0 5px; 91 | } -------------------------------------------------------------------------------- /docs/_sass/fonts.scss: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE in the project root for license information. 2 | // Derived from https://www.npmjs.com/package/office-ui-fabric-react 3 | 4 | // Font directory and paths 5 | $ms-font-cdn-path: 'https://static2.sharepointonline.com/files/fabric/assets/fonts' !default; 6 | 7 | // Fallback fonts, if specified system or web fonts are unavailable. 8 | $ms-font-family-fallbacks: 'Segoe UI', -apple-system, BlinkMacSystemFont, 'Roboto', 'Helvetica Neue', sans-serif !default; 9 | 10 | $ms-font-size-su: 42px !default; 11 | $ms-font-size-xxl: 28px !default; 12 | $ms-font-size-xl-plus: 24px !default; 13 | $ms-font-size-xl: 21px !default; 14 | $ms-font-size-l: 17px !default; 15 | $ms-font-size-m-plus: 15px !default; 16 | $ms-font-size-m: 14px !default; 17 | $ms-font-size-s-plus: 13px !default; 18 | $ms-font-size-s: 12px !default; 19 | $ms-font-size-xs: 11px !default; 20 | $ms-font-size-mi: 10px !default; 21 | 22 | $ms-font-weight-light: 100 !default; 23 | $ms-font-weight-semilight: 300 !default; 24 | $ms-font-weight-regular: 400 !default; 25 | $ms-font-weight-semibold: 600 !default; 26 | $ms-font-weight-bold: 700 !default; 27 | 28 | @mixin ms-font-face($font-family-name, $cdn-folder, $cdn-font-name: "segoeui") { 29 | @font-face { 30 | font-family: $font-family-name; 31 | src: url("#{$ms-font-cdn-path}/#{$cdn-folder}/#{$cdn-font-name}-light.woff2") format("woff2"), 32 | url("#{$ms-font-cdn-path}/#{$cdn-folder}/#{$cdn-font-name}-light.woff") format("woff"); 33 | font-weight: $ms-font-weight-light; 34 | font-style: normal; 35 | } 36 | 37 | @font-face { 38 | font-family: $font-family-name; 39 | src: url("#{$ms-font-cdn-path}/#{$cdn-folder}/#{$cdn-font-name}-semilight.woff2") format("woff2"), 40 | url("#{$ms-font-cdn-path}/#{$cdn-folder}/#{$cdn-font-name}-semilight.woff") format("woff"); 41 | font-weight: $ms-font-weight-semilight; 42 | font-style: normal; 43 | } 44 | 45 | @font-face { 46 | font-family: $font-family-name; 47 | src: url("#{$ms-font-cdn-path}/#{$cdn-folder}/#{$cdn-font-name}-regular.woff2") format("woff2"), 48 | url("#{$ms-font-cdn-path}/#{$cdn-folder}/#{$cdn-font-name}-regular.woff") format("woff"); 49 | font-weight: $ms-font-weight-regular; 50 | font-style: normal; 51 | } 52 | 53 | @font-face { 54 | font-family: $font-family-name; 55 | src: url("#{$ms-font-cdn-path}/#{$cdn-folder}/#{$cdn-font-name}-semibold.woff2") format("woff2"), 56 | url("#{$ms-font-cdn-path}/#{$cdn-folder}/#{$cdn-font-name}-semibold.woff") format("woff"); 57 | font-weight: $ms-font-weight-semibold; 58 | font-style: normal; 59 | } 60 | 61 | @font-face { 62 | font-family: $font-family-name; 63 | src: url("#{$ms-font-cdn-path}/#{$cdn-folder}/#{$cdn-font-name}-bold.woff2") format("woff2"), 64 | url("#{$ms-font-cdn-path}/#{$cdn-folder}/#{$cdn-font-name}-bold.woff") format("woff"); 65 | font-weight: $ms-font-weight-bold; 66 | font-style: normal; 67 | } 68 | } 69 | 70 | @include ms-font-face('Segoe UI Web (West European)', 'segoeui-westeuropean'); 71 | 72 | $ms-font-family-west-european: 'Segoe UI Web (West European)', $ms-font-family-fallbacks !default; -------------------------------------------------------------------------------- /docs/_sass/theme.scss: -------------------------------------------------------------------------------- 1 | @import "code"; 2 | @import "fonts"; 3 | @import "cosmos"; 4 | 5 | body { 6 | position: relative; 7 | font-weight: $ms-font-size-m; 8 | } 9 | 10 | body, 11 | html { 12 | font-family: $ms-font-family-west-european; 13 | } 14 | 15 | p { 16 | font-weight: $ms-font-weight-regular; 17 | } 18 | 19 | main { 20 | 21 | a:active, 22 | a:hover { 23 | color: #50e6ff; 24 | } 25 | 26 | a:visited { 27 | color: #0050C5; 28 | } 29 | 30 | a.btn { 31 | &:visited { 32 | color: #50e6ff; 33 | } 34 | 35 | &:hover { 36 | color: #243a5e; 37 | } 38 | } 39 | } 40 | 41 | a { 42 | word-wrap: break-word; 43 | } 44 | 45 | main ol ol, 46 | main ul ul { 47 | margin: 0 0 0 20px; 48 | } 49 | 50 | main ul ul>li { 51 | list-style-type: circle; 52 | } 53 | 54 | main ul ul ul>li { 55 | list-style-type: square; 56 | } 57 | 58 | main ol ol>li { 59 | list-style-type: lower-alpha; 60 | } 61 | 62 | main ol ol ol>li { 63 | list-style-type: lower-roman; 64 | } 65 | 66 | html { 67 | -ms-text-size-adjust: 100%; 68 | -webkit-text-size-adjust: 100%; 69 | box-sizing: border-box; 70 | height: 100%; 71 | } 72 | 73 | body { 74 | background: #fff; 75 | color: #222; 76 | 77 | line-height: 160%; 78 | min-height: 100%; 79 | height: auto !important; 80 | } 81 | 82 | a { 83 | color: #0050C5; 84 | cursor: pointer; 85 | text-decoration: none; 86 | } 87 | 88 | a:hover { 89 | text-decoration: underline; 90 | } 91 | 92 | small { 93 | font-weight: $ms-font-size-s; 94 | } 95 | 96 | dl, 97 | ol, 98 | ul { 99 | margin-bottom: 1rem; 100 | } 101 | 102 | blockquote { 103 | border-color: #bff1ff; 104 | color: inherit; 105 | 106 | padding: 20px; 107 | margin-top: 15px; 108 | border-radius: 6px; 109 | } 110 | 111 | blockquote:before { 112 | content: "\0024D8\00a0Note"; 113 | color: #FFFFFF; 114 | 115 | } 116 | 117 | article { 118 | img { 119 | max-width: 85%; 120 | display: block; 121 | margin-left: auto; 122 | margin-right: auto; 123 | } 124 | 125 | &.home { 126 | img { 127 | max-width: 100%; 128 | } 129 | } 130 | } 131 | 132 | .navbar-light { 133 | background-color: #d2d2d2; 134 | } 135 | 136 | .navbar-text a { 137 | color: #505050; 138 | } 139 | 140 | .bg-light { 141 | background-color: #d2d2d2; 142 | } 143 | 144 | .bg-black { 145 | background-color: #000000; 146 | } 147 | 148 | .text-black { 149 | color: #000000; 150 | } 151 | 152 | .bg-azure { 153 | background-color: #50e6ff; 154 | } 155 | 156 | .bg-note, 157 | blockquote { 158 | background-color: #243a5e; 159 | 160 | p { 161 | color: #FFFFFF; 162 | } 163 | } 164 | 165 | .text-azure { 166 | color: #50e6ff; 167 | } 168 | 169 | h1, 170 | h2, 171 | h3, 172 | h4, 173 | h5, 174 | h6 { 175 | font-weight: $ms-font-weight-semibold; 176 | text-rendering: optimizeLegibility; 177 | word-wrap: break-word; 178 | } 179 | 180 | h1 { 181 | font-size: $ms-font-size-xxl; 182 | } 183 | 184 | h2 { 185 | font-size: $ms-font-size-xxl; 186 | margin-top: 10px; 187 | } 188 | 189 | h3 { 190 | font-size: $ms-font-size-xl-plus; 191 | } 192 | 193 | h4 { 194 | font-size: $ms-font-size-xl; 195 | } 196 | 197 | h5 { 198 | font-size: $ms-font-size-l; 199 | } 200 | 201 | h6 { 202 | font-size: $ms-font-size-m-plus; 203 | } 204 | 205 | .title { 206 | font-style: normal; 207 | font-weight: $ms-font-weight-semibold; 208 | line-height: 1.3; 209 | text-rendering: optimizeLegibility; 210 | word-wrap: break-word; 211 | margin-bottom: 10px; 212 | 213 | margin-top: 32px; 214 | } 215 | 216 | nav.toc { 217 | margin-top: 24px !important; 218 | overflow-y: auto !important; 219 | flex-grow: 1 !important; 220 | } 221 | 222 | nav.toc a.nav-link, 223 | nav.toc li.nav-item, 224 | nav.toc ul.nav { 225 | outline: #000 solid 0 !important; 226 | -moz-box-shadow: inset 0 0 0 0 #000 !important; 227 | -webkit-box-shadow: inset 0 0 00 #000 !important; 228 | box-shadow: inset 0 0 0 0 #000 !important; 229 | } 230 | 231 | .toc a:focus, 232 | .toc li:focus, 233 | .toc ul:focus { 234 | -moz-box-shadow: inset 0 0 0 2px #0050C5; 235 | -webkit-box-shadow: inset 0 0 0 2px #0050C5; 236 | box-shadow: inset 0 0 0 2px #0050C5; 237 | } 238 | 239 | nav.toc ul.nav { 240 | margin-bottom: 0; 241 | padding-left: 10px; 242 | } 243 | 244 | nav.toc>ul.nav { 245 | display: block; 246 | margin-left: 0; 247 | padding-left: 0; 248 | } 249 | 250 | nav.toc>ul.nav a.nav-link { 251 | padding: 0.75rem 0.25rem; 252 | } 253 | 254 | ul.nav { 255 | li { 256 | list-style: none; 257 | } 258 | } 259 | 260 | nav.toc>ul.nav a.nav-link, 261 | nav.toc>ul.nav span { 262 | display: block; 263 | 264 | line-height: 1.3; 265 | margin-left: .5rem; 266 | margin-right: 1rem; 267 | word-wrap: break-word; 268 | color: #222; 269 | } 270 | 271 | nav.toc>ul.nav a.nav-link { 272 | color: #243a5e; 273 | text-decoration: none; 274 | } 275 | 276 | nav.toc>ul.nav a.nav-link:hover { 277 | color: #243a5e; 278 | text-decoration: underline; 279 | } 280 | 281 | nav.toc>ul.nav a.nav-link.active { 282 | background-color: #243a5e; 283 | color: #50e6ff; 284 | } 285 | 286 | main th, 287 | pre { 288 | text-align: left; 289 | } 290 | 291 | main table caption, 292 | main td, 293 | main th { 294 | border-style: solid; 295 | border-color: #e3e3e3; 296 | } 297 | 298 | main td, 299 | main th { 300 | word-wrap: break-word; 301 | } 302 | 303 | main table { 304 | border-collapse: collapse; 305 | border-spacing: 0; 306 | table-layout: auto; 307 | width: 100%; 308 | 309 | } 310 | 311 | main table caption { 312 | 313 | font-weight: $ms-font-weight-bold; 314 | letter-spacing: 2px; 315 | text-transform: uppercase; 316 | padding: 1.2em; 317 | border-width: 0 0 1px; 318 | text-align: right; 319 | } 320 | 321 | main td, 322 | main th { 323 | display: table-cell; 324 | padding: 12px 16px; 325 | line-height: 1.5; 326 | vertical-align: top; 327 | border-width: 1px 0 0; 328 | } 329 | 330 | main th { 331 | 332 | font-weight: $ms-font-weight-bold; 333 | vertical-align: bottom; 334 | border-width: 0 0 1px; 335 | } 336 | 337 | main table>caption+thead>tr:first-child>td, 338 | main table>colgroup+thead>tr:first-child>td, 339 | main table>thead:first-child>tr:first-child>td { 340 | border-top: 0; 341 | } 342 | 343 | main .table-striped>tbody>tr:nth-of-type(odd) { 344 | background-color: rgba(0, 0, 0, 0.05); 345 | } 346 | 347 | main.extra-padding { 348 | padding-bottom: 200px; 349 | } -------------------------------------------------------------------------------- /docs/assets/css/style.scss: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | 4 | @import "theme"; 5 | -------------------------------------------------------------------------------- /docs/assets/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/assets/img/logo.png -------------------------------------------------------------------------------- /docs/assets/img/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Icon-databases-121 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /docs/bulk-executor.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Add the bulk executor feature 3 | description: Add the bulk executor to your code sample, which is an Azure Cosmos DB feature that allows bulk inserts, updates, and deletes. 4 | ms.service: cosmos-db 5 | ms.topic: reference 6 | ms.date: 08/19/2022 7 | author: seesharprun 8 | ms.author: sidandrews 9 | ms.reviewer: mjbrown 10 | sequence: 13 11 | --- 12 | 13 | # Bulk Execution 14 | 15 | Bulk Execution is an Azure Cosmos DB feature that allows bulk inserts, updates, and deletes. When inserts and updates occur, they appear in the change feed. Bulk Execution is part of the Java V4 SDK for Azure Cosmos DB. 16 | 17 | 18 | ## Add application properties 19 | 20 | Add details of the collection where bulk execution will be used to the *application-default.properties* file: 21 | 22 | ```properties 23 | # values for bulk executor 24 | azure.cosmos.collection=pet-supplies 25 | azure.cosmos.partitionKey=documentType 26 | azure.cosmos.collectionThroughput = 100000; 27 | ``` 28 | 29 | ## Update code 30 | 31 | All bulk operations occur in `BulkExecutorService`. 32 | 33 | A controller calls the bulk operations, with the following endpoints: 34 | 35 | - `/api/bulk POST`: Bulk import 36 | - `/api/bulk PUT`: Bulk update 37 | - `/api/bulk DELETE`: Bulk delete 38 | 39 | In the Postman collection, we've included a section for you to try each of these bulk operations against the sample code. 40 | 41 | ## Learn more 42 | 43 | [Azure Cosmos DB bulk executor library overview](https://docs.microsoft.com/azure/cosmos-db/bulk-executor-overview) 44 | 45 | [Next | Schema design considerations](schema-considerations.md){: .btn .btn-primary .btn-lg } -------------------------------------------------------------------------------- /docs/change-feed-with-cosmos-db-trigger-function.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Create an Azure Cosmos DB trigger for Azure Functions in Java 3 | description: Learn how to create an Azure Cosmos DB trigger for Azure Functions in Java. 4 | ms.service: cosmos-db 5 | ms.topic: reference 6 | ms.date: 08/19/2022 7 | author: seesharprun 8 | ms.author: sidandrews 9 | ms.reviewer: mjbrown 10 | sequence: 9 11 | --- 12 | 13 | # Create an Azure Cosmos DB trigger for Azure Functions in Java 14 | 15 | In the previous article, you used the change feed processor with reactive programming to monitor the change feed. As an alternative, you can also monitor the change feed by using an [Azure Cosmos DB trigger](https://docs.microsoft.com/azure/azure-functions/functions-create-cosmos-db-triggered-function) for Azure Functions. 16 | 17 | The following code sample, shows how to use an Azure Function App to listen to the change feed, and then send the changes to an event store. 18 | 19 | ## Set up the Azure Function App 20 | 21 | To use [Azure Functions](https://docs.microsoft.com/azure/azure-functions/), you need to create a storage account. As you create your storage account, ensure you stay within the following guidelines: 22 | 23 | - Storage account names must be between 3 and 24 characters in length. 24 | 25 | - Use numbers and lowercase letters only. 26 | 27 | You can use the following command as a guide: 28 | 29 | ```azurecli 30 | az storage account create --name petsuppliesstorage -g pet-supplies-demo-rg --location eastus --sku Standard_LRS 31 | ``` 32 | 33 | 1. Store your Azure Storage connection string in this environment variable, as you might need it later: 34 | 35 | ```azurecli 36 | AZURE_WEBJOBS_STORAGE=$(az storage account show-connection-string --name petsuppliesstorage -g pet-supplies-demo-rg --query "connectionString" -o tsv) 37 | ``` 38 | 39 | 1. Store your Azure Cosmos DB connection string in an environment variable: 40 | 41 | ```azurecli 42 | AZURE_COSMOS_CONNECTION_STRING=$(az cosmosdb keys list --type connection-strings --name pet-supplies-demo -g pet-supplies-demo-rg9 --query "connectionStrings[0].connectionString" -o tsv) 43 | ``` 44 | 45 | ## Azure Function App code 46 | 47 | Use Azure Functions with the Azure Cosmos DB trigger for another example of how to process the change feed. You can use a Maven archetype to scaffold Azure Functions. Because Java 11 functionality in Azure Functions is in preview, this section uses Java 8. 48 | 49 | 1. From an empty project folder, run the following Maven command: 50 | 51 | ```bash 52 | mvn archetype:generate -DarchetypeGroupId="com.microsoft.azure" -DarchetypeArtifactId="azure-functions-archetype" -DadvancedOptions 53 | ``` 54 | 55 | Use the following settings: 56 | 57 | - groupId: com 58 | - artifactId: function 59 | - package: com.function 60 | 61 | 1. When you're prompted, input *N* to trigger the advanced options prompts. The additional settings include: 62 | 63 | - appName: cosmosChangeFeedProcessorFunction 64 | - appRegion: \ 65 | - resourceGroup: pet-supplies-demo-rg 66 | - trigger: CosmosDBTrigger 67 | 68 | The Maven archetype generates boilerplate scaffolding. 69 | 70 | 1. In *Function.java*, populate the following values: 71 | 72 | - databaseName: pet-supplies 73 | - collectionName: pet-supplies 74 | - leaseCollectionName: lease 75 | - connectionStringSetting: \ 76 | 77 | \ is the connection string setting value, which you can store in *local.settings.json*. 78 | 79 | 1. Update the `@FunctionName` annotation to have a more meaningful name such as CosmosDBChangeFeedMonitor. 80 | 81 | 1. The archetype also creates a file named *local.settings.json* at the same level as the *host.json* file. Update this file with the following settings: 82 | 83 | ```json 84 | { 85 | "IsEncrypted": false, 86 | "Values": { 87 | "AzureWebJobsStorage": "paste the value from AZURE_WEBJOBS_STORAGE", 88 | "AzureCosmosDBConnectionString": "paste the value from AZURE_COSMOS_CONNECTION_STRING", 89 | "FUNCTIONS_WORKER_RUNTIME": "java" 90 | } 91 | } 92 | ``` 93 | 94 | 1. Run this function locally with the following commands: 95 | 96 | ```bash 97 | mvn clean package 98 | func start host 99 | ``` 100 | 101 | ## Deploy the function to Azure 102 | 103 | Use the [Maven Plugin for Azure Functions](https://github.com/microsoft/azure-maven-plugins/wiki/Azure-Functions) to deploy your function to Azure. 104 | 105 | 1. Store your connection information in app settings variables in your Azure App Service resource. 106 | 107 | 1. In the *pom.xml* file, in the section for the Azure Functions Maven Plugin, add the following properties to the **appSettings** section: 108 | 109 | ```xml 110 | 111 | AzureWebJobsStorage 112 | ${AZURE_WEBJOBS_STORAGE} 113 | 114 | 115 | 116 | ${AZURE_COSMOS_CONNECTION_STRING} 117 | 118 | ``` 119 | 120 | The `@CosmosDBTrigger` annotation's connectionStringSetting property looks for the \ application setting. 121 | 122 | 1. To deploy the code to Azure, run: 123 | 124 | ```bash 125 | mvn azure-functions:deploy 126 | ``` 127 | 128 | The plugin creates the following items: 129 | 130 | - App Service plan 131 | - Application Insights component 132 | - Azure Function App with the Java runtime 133 | 134 | 1. After the code is successfully deployed, confirm your app settings were passed properly by using the following commands: 135 | 136 | ```azurecli 137 | az functionapp config appsettings list -g pet-supplies-demo-rg --name cosmosChangeFeedProcessorFunction --query "[? name=='AzureCosmosDBConnectionString']" 138 | 139 | az functionapp config appsettings list -g pet-supplies-demo-rg --name cosmosChangeFeedProcessorFunction --query "[? name=='AzureWebJobsStorage']" 140 | ``` 141 | 142 | 1. You can also view these values in the Azure portal. 143 | 144 | ![Screenshot showing the Configuration page of the Azure Function App.](media/change-feed-with-cosmos-db-trigger-function/function-app-configuration.png) 145 | 146 | If you make changes to your Contoso Pet Supplies data, it should trigger your Azure Function to use those changes. There's a lag time between the action and when it appears in the logs. 147 | 148 | 1. In the Azure portal, navigate to the function on the Function App resource and select **Monitor**. 149 | 150 | The function app that was invoked for your changes appears. 151 | 152 | 1. If you select timestamp, a panel with invocation details appears. 153 | 154 | ![Screenshot showing the Monitor page of the Azure Function App.](media/change-feed-with-cosmos-db-trigger-function/function-app-monitor.png) 155 | 156 | [Next | Event sourcing](event-sourcing.md){: .btn .btn-primary .btn-lg } 157 | -------------------------------------------------------------------------------- /docs/crud-operations-with-cosmos-db.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: CRUD operations with Azure Cosmos DB 3 | description: Learn about create, read, update, and delete (CRUD) operations in an Azure Cosmos database and how to implement them. 4 | ms.service: cosmos-db 5 | ms.topic: reference 6 | ms.date: 08/19/2022 7 | author: seesharprun 8 | ms.author: sidandrews 9 | ms.reviewer: mjbrown 10 | sequence: 7 11 | --- 12 | 13 | # CRUD operations with Azure Cosmos DB 14 | 15 | To do create, read, update, and delete (CRUD) operations on records in Azure Cosmos DB, a small amount of code is required. Spring Data for the Azure Cosmos DB for NoSQL artifact supports the `CrudRepository` and `ReactiveCrudRepository` interfaces. It also includes `CosmosRepository` and `ReactiveCosmosRepository`. 16 | 17 | For this application, you use `ReactiveCosmosRepository`. 18 | 19 | The code is structured with: 20 | 21 | - Controllers serving as API endpoints 22 | 23 | - Repositories as interfaces 24 | 25 | - Services implementing repositories 26 | 27 | ## Repositories overview 28 | 29 | This application has repositories for: 30 | 31 | - Customers 32 | 33 | - Manufacturers 34 | 35 | - Products 36 | 37 | - Wish lists 38 | 39 | Each of the reactive repositories follows this pattern: 40 | 41 | ```java 42 | @Repository 43 | public interface ThingRepository extends 44 | ReactiveCosmosRepository { 45 | Mono deleteById(String thingId, PartitionKey key); 46 | Flux findAll(PartitionKey key); 47 | Mono findById(String thingId, PartitionKey key); 48 | Mono save(Thing thing); 49 | } 50 | ``` 51 | 52 | Repositories in Spring Data for the Azure Cosmos DB for NoSQL artifact support these additional operations than the ones used in the sample code: 53 | 54 | - Delete entity 55 | 56 | - Delete all 57 | 58 | ## Implement CRUD operations 59 | 60 | Most Spring Data interface functions use default implementations. However, because the wish list object is complex, it's necessary to add a few more functions: 61 | 62 | - `findByCustomerId` 63 | 64 | - `findByProductId` 65 | 66 | `findByCustomerId` is annotated with a query to filter on the customer ID. `findByProductId` searches for all wish lists that have a particular product ID in their array of product IDs. These IDs re annotated with the `@Query` annotation to use a custom Azure Cosmos DB SQL query. As a wish list is tied to one customer, the query for `findByCustomerId` makes use of the equals (=) operator. Because a wishlist can have many products, the query for `findByProductId` makes use of the `ARRAY_CONTAINS()` function to check the array of product IDs tied to a wishlist. 67 | 68 | If you need to customize queries or add additional queries, use the `@Query` annotation and Azure Cosmos DB's SQL syntax for the query. 69 | 70 | ## Partial document updates 71 | 72 | To make a small change to an object, you don't necessarily need to do a full document update. Azure Cosmos DB supports partial document updates, by using PATCH updates. Microsoft implements an endpoint in its Products API to update product prices as partial updates. 73 | 74 | For partial document updates, note the following points: 75 | 76 | - Because you need to suppress attempts to bind queries to the method, you should assign a Query annotation over the method in the repository. 77 | 78 | - Partial document updates are in Azure Cosmos DB Java SDK v4, not Spring Data for the Azure Cosmos DB for NoSQL artifact. 79 | 80 | ## Learn more 81 | 82 | - [Azure Cosmos DB PDF query cheat sheets](https://docs.microsoft.com/azure/cosmos-db/sql/query-cheat-sheet) 83 | 84 | - [Getting started with SQL queries](https://docs.microsoft.com/azure/cosmos-db/sql/sql-query-getting-started) 85 | 86 | - [Working with arrays and objects in Azure Cosmos DB](https://docs.microsoft.com/azure/cosmos-db/sql/sql-query-object-array) 87 | 88 | - [Partial document update in Azure Cosmos DB](https://docs.microsoft.com/azure/cosmos-db/partial-document-update) 89 | 90 | - [Frequently asked questions about partial document update in Azure Cosmos DB](https://docs.microsoft.com/azure/cosmos-db/partial-document-update-faq) 91 | 92 | [Next | Azure Cosmos DB Change Feed](change-feed-concepts.md){: .btn .btn-primary .btn-lg } 93 | -------------------------------------------------------------------------------- /docs/deploy-to-azure-app-service.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Deploy to Azure App Service 3 | description: Learn how to deploy to Azure App Service. 4 | ms.service: cosmos-db 5 | ms.topic: reference 6 | ms.date: 08/19/2022 7 | author: seesharprun 8 | ms.author: sidandrews 9 | ms.reviewer: mjbrown 10 | sequence: 6 11 | --- 12 | 13 | # Deploy to Azure App Service 14 | 15 | [Azure App Service](https://docs.microsoft.com/azure/app-service/) is one of the ways to host Java applications in Azure. After your sample app is running locally, use the [Maven Plugin for Azure App Service](https://github.com/microsoft/azure-maven-plugins/blob/develop/azure-webapp-maven-plugin/) to deploy the sample app to Azure App Service. This tool creates the resources if they don't exist. 16 | 17 | ## Modify the pom.xml file 18 | 19 | To deploy to Azure App Service, you don't need to install any separate components. The *pom.xml* file has a reference in the \ section for the `azure-webapp-maven-plugin` artifact. 20 | 21 | In the *pom.xml* file, update the following properties in the \ section: 22 | 23 | - azure.webapp.AppName: \ 24 | - azure.webapp.appServicePlanName: \ 25 | - azure.webapp.region: \ 26 | - azure.webapp.resourceGroup: \ 27 | 28 | ## Deploy the application 29 | 30 | The plugin section in the *pom.xml* file has an \ section, which contains the environment variables and their values. These variable values are copied to the Azure App Service app's settings. 31 | 32 | ![Screenshot showing the App Service Configuration page.](media/deploy-to-azure-app-service/app-service-configuration.png) 33 | 34 | 1. After you update your configuration information with your values, deploy the application by using the following command: 35 | 36 | ```bash 37 | mvn package azure-webapp:deploy 38 | ``` 39 | 40 | When the project is deployed, a success message appears with a URL for your Azure App Service application. 41 | 42 | 1. To verify a successful deployment, run the Curl command on the URL and ensure you get an HTTP status of 200. 43 | 44 | [Next | CRUD Operations with Azure Cosmos DB](crud-operations-with-cosmos-db.md){: .btn .btn-primary .btn-lg } 45 | -------------------------------------------------------------------------------- /docs/event-sourcing.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Update the Azure Cosmos DB trigger code for event sourcing 3 | description: Learn how to update the Azure Cosmos DB trigger code you previously created for event sourcing and apply it to Azure Cosmos DB change feed. 4 | ms.service: cosmos-db 5 | ms.topic: reference 6 | ms.date: 08/19/2022 7 | author: seesharprun 8 | ms.author: sidandrews 9 | ms.reviewer: mjbrown 10 | sequence: 10 11 | --- 12 | 13 | # Update the Azure Cosmos DB trigger code for event sourcing 14 | 15 | The *event sourcing* pattern is a design pattern that captures events in the same order as they occur. You use this pattern for tasks such as audit trails and data migration. You can also use it as the source of truth in nonrelational data stores when you work with event consistency. The Azure Cosmos DB change feed is a good source to use for event sourcing because it's an append-only feed that preserves the order of changes. It also captures data add and update events. 16 | 17 | The following code sample builds on the Azure Cosmos DB trigger code for Azure Functions. It sends events to Azure Event Hubs to trigger notifications for product updates. The goal is to use the Azure Cosmos DB change feed to trigger your function, which will then send its output to Azure Event Hubs. 18 | 19 | ![Diagram showing the Azure Cosmos DB trigger.](media/event-sourcing/cosmos-db-trigger.png) 20 | 21 | ## Create Azure Event Hubs resources 22 | 23 | 1. To work with [Azure Event Hubs](https://docs.microsoft.com/azure/event-hubs/), you first need to create an Azure Event Hubs namespace: 24 | 25 | ```azurecli 26 | az eventhubs namespace create --name pet-supplies-events -g pet-supplies-demo-rg -l eastus 27 | ``` 28 | 29 | 1. After you create the namespace, you can then create the event hub: 30 | 31 | ```azurecli 32 | az eventhubs eventhub create --name pet-supplies-events -g pet-supplies-demo-rg --namespace-name pet-supplies-events 33 | ``` 34 | 35 | 1. After you create the namespace and event hub, you're ready to create an authorization rule for accessing the event hub. In this case, you want to publish to the event hub and then view what's in it. To do so, use the following command: 36 | 37 | ```azurecli 38 | az eventhubs eventhub authorization-rule create --resource-group pet-supplies-demo-rg --name pet-supplies-events-auth --eventhub-name pet-supplies-events --namespace-name pet-supplies-events --rights Listen Send 39 | ``` 40 | 41 | 1. Store the event hub connection string in an environment variable: 42 | 43 | ```azurecli 44 | AZURE_EVENT_HUB_CONNECTION=$(az eventhubs eventhub authorization-rule keys list --eventhub-name pet-supplies-events -g pet-supplies-demo-rg --namespace-name pet-supplies-events --name pet-supplies-events-auth --query primaryConnectionString) 45 | ``` 46 | 47 | ## Update the code 48 | 49 | You need to update your function to handle the `@EventHubOutput` annotation. You also need to update the return type and return the array of objects returned by the change feed. The updated class in *Function.java* should look like this: 50 | 51 | ```java 52 | public class Function { 53 | 54 | /** 55 | 56 | * This function will be invoked when there are inserts or updates in the specified database and collection. 57 | 58 | */ 59 | 60 | @FunctionName("CosmosDBChangeFeedMonitor") 61 | @EventHubOutput(name = "event", eventHubName = "pet-supplies-events", connection = "AzureEventHubConnection") 62 | 63 | public Object[] pushToEventGrid( 64 | @CosmosDBTrigger( 65 | name = "items", 66 | databaseName = "pet-supplies", 67 | collectionName = "pet-supplies", 68 | leaseCollectionName="lease", 69 | connectionStringSetting = "AzureCosmosDBConnectionString", 70 | createLeaseCollectionIfNotExists = true 71 | ) 72 | Object[] items, 73 | final ExecutionContext context 74 | ) { 75 | context.getLogger().info("Azure Cosmos DB Java trigger function executed."); 76 | context.getLogger().info("Documents count: " + items.length); 77 | return items; 78 | } 79 | } 80 | ``` 81 | 82 | ## Update configurations 83 | 84 | 1. Update the *local.settings.json* file to include information from the event hub connection: 85 | 86 | ```json 87 | { 88 | "IsEncrypted": false, 89 | "Values": { 90 | "AzureWebJobsStorage": "%AZURE_WEBJOBS_STORAGE%", 91 | "AzureCosmosDBConnectionString": "%AZURE_COSMOS_CONNECTION_STRING%", 92 | "AzureEventHubConnection": "%AZURE_EVENT_HUB_CONNECTION%", 93 | "FUNCTIONS_WORKER_RUNTIME": "java" 94 | } 95 | } 96 | ``` 97 | 98 | 1. Update the *pom.xml* file to include your new environment variable: 99 | 100 | ```xml 101 | 102 | \ 103 | ${AZURE_EVENT_HUB_CONNECTION} 104 | 105 | ``` 106 | 107 | The `@EventHubOutput` annotation's connection property looks for the \ application setting. 108 | 109 | ## Deploy to Azure App Service 110 | 111 | 1. Deploy the previous changes to Azure App Service by using the following commands: 112 | 113 | ```bash 114 | mvn clean package 115 | mvn azure-functions:deploy 116 | ``` 117 | 118 | After your changes deploy successfully, you should see a new environment variable: 119 | 120 | ![Screenshot showing the Function App Configuration page.](media/event-sourcing/function-app-configuration.png) 121 | 122 | 1. To test the deployment, change your Contoso Pet Supplies data to trigger the change feed. 123 | 124 | 1. Wait about 10 minutes, then check Azure Event Hubs for events in the log that are ready to be consumed by its subscribers. 125 | 126 | ![Screenshot showing the Azure Event Hubs Instance Overview page.](media/event-sourcing/event-hubs-instance-overview.png) 127 | 128 | [Next | Sending Notifications with Azure Logic Apps](send-notifications-with-azure-logic-apps.md){: .btn .btn-primary .btn-lg } 129 | -------------------------------------------------------------------------------- /docs/foreword.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Cloud-Scale Data for Spring Developers 3 | description: Learn how the Cloud-Scale Data for Spring Developers Quick Start Guide can help you bring cloud-native Java applications to Azure. 4 | ms.service: cosmos-db 5 | ms.topic: reference 6 | ms.date: 08/19/2022 7 | author: seesharprun 8 | ms.author: sidandrews 9 | ms.reviewer: mjbrown 10 | sequence: 0 11 | --- 12 | 13 | # Cloud-Scale Data for Spring Developers Quickstart guide: Foreword 14 | 15 | Welcome to the Cloud-Scale for Spring Developers Quick Start Guide. The purpose of this guide is to help you build cloud-native Java applications in Azure. You'll gain insights about using NoSQL and why you should consider Azure Cosmos DB, our fully managed, distributed NoSQL database service on Azure. 16 | 17 | These insights are designed to be useful whether you're starting with a NoSQL background or coming into a project with a relational mindset. Data isn't the only thing involved in an application, and this guide will take you through working with other Azure services that integrate well with Azure Cosmos DB. 18 | 19 | You'll learn how to host Java applications in [Azure Spring Apps](https://azure.microsoft.com/services/spring-apps/) or set up notifications with [Azure Functions](https://azure.microsoft.com/services/functions/) and [Azure Logic Apps](https://azure.microsoft.com/services/logic-apps/). 20 | 21 | ## What this guide covers 22 | 23 | Real-world examples will showcase Azure platforms. Since the focus is on cloud-native Java applications, this guide will use Java with Spring Boot throughout. 24 | 25 | In addition, you'll learn how to use Azure Cosmos DB for your data needs, such as storing product information in Azure Cosmos DB or sending notifications with Azure Logic Apps to users when products have changed. 26 | 27 | Retail situations will be included, as well as suggestions for other business cases. By the end of this guide, you should have the confidence to build cloud-native Java applications in Azure with Azure Cosmos DB as a data store. You'll be able to run an application in an Azure pay-as-you-go account with the Azure Cosmos DB free tier. 28 | 29 | ## Not covered 30 | 31 | This guide doesn't explain how to migrate existing Java applications to Azure. Migrating existing Java applications is covered in the [Java to Azure migration strategy documentation](/azure/developer/java/migration/). As well, this guide doesn't cover relational data storage in Azure. It isn't intended to be a complete compendium of all things Java and Azure, though there will be many Azure offerings showcased. The guide also does not offer a complete coverage of the Java SDK for Azure Cosmos DB, or the wider Java ecosystem for Azure Cosmos DB. It is not intended as a comprehensive recommendation for how to build *any* Java app using Azure Cosmos DB, but rather as a guide for how to get started with Spring Boot, featuring the `azure-spring-boot-starter-cosmos` library, as well as coverage of some core Java V4 SDK features and concepts. 32 | 33 | ## Scenario introduction 34 | 35 | Throughout this guide, we'll examine a pet store eCommerce scenario to showcase Azure platforms. In this example, a fictional company called Contoso has acquired an online pet supplies store that's considering migrating their Java eCommerce platform to Azure. 36 | 37 | ## Build Your Apps for Free on Azure 38 | 39 | Start building your next Java app with Azure by taking advantage of the free app, data, and AI services. New Azure customers can sign up for an Azure Free Account to take advantage of additional free offerings. [Visit the Azure Free Account page for more details](https://azure.microsoft.com/free/). 40 | 41 | * Azure Cosmos DB 1000 RU/s + 25GB Storage (monthly) 42 | * Azure DevOps with unlimited private Git Repos for up to 5 users 43 | * Azure Kubernetes Services (AKS) with free Cluster Management 44 | * Azure Functions with up to 1M requests for free 45 | * Azure Cognitive Services up to 30,000 transactions free 46 | 47 | [Next | Introduction to NoSQL](intro-nosql.md){: .btn .btn-primary .btn-lg } -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Cloud-Scale Data for Spring Developers 3 | description: The Cloud-Scale Data for Spring Developers Quick Start Guide is a guide for bringing Cloud Native Java applications to Azure and using Azure Cosmos DB for your data needs. 4 | ms.service: cosmos-db 5 | ms.topic: overview 6 | ms.date: 08/19/2022 7 | author: seesharprun 8 | ms.author: sidandrews 9 | ms.reviewer: mjbrown 10 | --- 11 | 12 | # Cloud-Scale Data for Spring Developers 13 | 14 | ## VERSION v1.0 15 | 16 | PUBLISHED BY 17 | 18 | Microsoft Azure Cosmos DB product team 19 | 20 | A division of Microsoft Corporation 21 | 22 | One Microsoft Way 23 | 24 | Redmond, Washington 98052-6399 25 | 26 | Copyright © 2022 by Microsoft Corporation 27 | 28 | All rights reserved. No part of the contents of this book may be reproduced or transmitted in any form or by any means without the written permission of the publisher. 29 | 30 | This book is provided "as-is" and expresses the author\'s views and opinions. The views, opinions and information expressed in this book, including URL and other Internet website references, may change without notice. 31 | 32 | Some examples depicted herein are provided for illustration only and are fictitious. No real association or connection is intended or should be inferred. 33 | 34 | Microsoft and the trademarks listed at on the "Trademarks" webpage are trademarks of the Microsoft group of companies. 35 | 36 | All other marks and logos are property of their respective owners. 37 | 38 | [Next | Foreword](foreword.md){: .btn .btn-primary .btn-lg } -------------------------------------------------------------------------------- /docs/intro-cosmos.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: What is Azure Cosmos DB? 3 | description: Learn about Azure Cosmos DB, Microsoft's fully managed, distributed NoSQL database offering on Azure. 4 | ms.service: cosmos-db 5 | ms.topic: reference 6 | ms.date: 08/19/2022 7 | author: seesharprun 8 | ms.author: sidandrews 9 | ms.reviewer: mjbrown 10 | sequence: 2 11 | --- 12 | 13 | # What is Azure Cosmos DB? 14 | 15 | Azure Cosmos DB is a fully managed, distributed NoSQL database service. It's a globally distributed, massively scalable, multi-model database service. Unlike many other non-relational databases, Azure Cosmos DB offers [five consistency models](#consistency-models) for data durability. 16 | 17 | ## Non-relational database 18 | 19 | While Azure SQL DB is the flagship Azure product for *relational* data, Azure Cosmos DB is the flagship product for *non-relational* data. Azure Cosmos DB supports document data such as product information on an eCommerce site, blog posts on a website, and user profiles. Other non-relational data could include column-family data such as content management, sensor logs, and time series data. Graph data is used for applications such as recommendation engines, fraud detection algorithms, networks, and other relationship trends. Azure Cosmos DB supports these non-relational data types and schema-less JSON. 20 | 21 | ## Globally distributed 22 | 23 | Global distribution is one of the key pillars of Azure Cosmos DB. It's built to support globally accessible data, with low latency at the 99th percentile, elastic scalable throughput, and high availability. Data in Azure Cosmos DB is automatically synchronized across replicas in multiple regions. Since it's a foundational part of Azure, Cosmos DB is distributed in all regions in the four key Azure cloud environments: 24 | 25 | * Azure public cloud 26 | * Azure Government 27 | * Azure Government for Department of Defense 28 | * Azure China 21Vianet 29 | 30 | Data can be configured to be readable and writeable across multiple regions. There are service-level agreements (SLAs) guaranteed for Azure Cosmos DB resources based on different conditions. For more information about the SLAs, see [SLA for Azure Cosmos DB](https://azure.microsoft.com/support/legal/sla/cosmos-db/). 31 | 32 | ## Massively scalable 33 | 34 | Azure Cosmos DB is horizontally scalable. Capacity can be added to increase storage and throughput as needed, scaling from tens to hundreds of millions of requests per second over multiple regions. With autoscaling capability, you can trust that Azure Cosmos DB will scale out when needed to accommodate surges in activity. 35 | 36 | Azure Cosmos DB can be configured to scale according to your needs. You can manually set throughput for when you have predictable request traffic. It can also autoscale to a pre-determined maximum throughput. 37 | 38 | While the system is massively scalable, there are quotas around resources such as the maximum storage across all items per partition. For more information, see [Azure Cosmos DB service quotas](https://docs.microsoft.com/azure/cosmos-db/concepts-limits). 39 | 40 | ## Maintenance 41 | 42 | Azure Cosmos DB's infrastructure is maintained by Microsoft. Other than configuring and tuning your application, you aren't responsible for the hardware, operating system, or any other infrastructure maintenance. 43 | 44 | ## Throughput and costs 45 | 46 | The cost of database operations in Azure Cosmos DB is expressed in a rate-based currency called Request Units (RUs). RUs are calculated based on usage of CPU, IOPS, and memory resources. For example, getting a 1-KB item by its partition key and ID is one RU. Throughput can be provisioned at the database level and at the container level. 47 | 48 | Traditional Azure Cosmos DB pricing for the provisioned throughput capacity mode is broken into two components: provisioned throughput and consumed storage. The serverless capacity mode is handled on usage. For more information on choosing the capacity mode, see [how to choose between provisioned throughput and serverless](https://docs.microsoft.com/azure/cosmos-db/throughput-serverless). 49 | 50 | For more information on managing costs, see [plan and manage costs for Azure Cosmos DB](https://docs.microsoft.com/azure/cosmos-db/plan-manage-costs). 51 | 52 | ## Multi-model with multiple APIs 53 | 54 | Azure Cosmos DB is considered multi-model because data can be stored in diverse ways. APIs can be used with each of these models. The models and their supported APIs in Azure Cosmos DB include: 55 | 56 | * Key-value data using Azure Cosmos DB for Table. 57 | * Column-family data using Azure Cosmos DB for Apache Cassandra. 58 | * Document data using Azure Cosmos DB for MongoDB . 59 | * Graph data using Azure Cosmos DB for Apache Gremlin. 60 | 61 | [Azure Cosmos DB for NoSQL ](https://docs.microsoft.com/azure/cosmos-db/scripts/cli/sql/create) is the main API for interacting with Azure Cosmos DB, used for querying JSON objects. When features are introduced, it's the first API to see the updates. This guide uses the SQL API. 62 | 63 | While the SQL API may suggest relational data could work in Azure Cosmos DB, this database platform was built with NoSQL in mind. The flavor of SQL with this API is designed for querying JSON data and structures. 64 | 65 | ## Consistency models 66 | 67 | Most non-relational databases support two consistency models: eventual and strong. However, Azure Cosmos DB supports five consistency models on a sliding scale. 68 | 69 | ![Diagram of consistency models in order: Eventual, Consistent Prefix, Session, Bounded Staleness, and Strong.](media/intro-cosmos/consistency_scale.svg) 70 | 71 | These models from weakest to strongest are: 72 | 73 | * Eventual 74 | * Consistent Prefix 75 | * Session 76 | * Bounded Staleness 77 | * Strong 78 | 79 | ### Eventual consistency 80 | 81 | *Eventual* is the weakest consistency offered by Azure Cosmos DB. Order isn't guaranteed for reading with the eventual consistency. Replicas eventually synchronize up in a break from writes. With the eventual consistency, it's possible to read older data rather than the most updated commit. 82 | 83 | ### Consistent Prefix consistency 84 | 85 | With *consistent prefix* consistency, reads won't see out-of-order writes. Not all writes may come through on a read, but their order is persisted. So, if three writes happen and then a read, the read may pick up the commit from write 1 or the commits from write 1 and write 2. However, it wouldn't pick up the writes out of order, such as write 1 and write 3, missing write 2. 86 | 87 | ### Session consistency 88 | 89 | *Session* is the mid-grade consistency offered in Azure Cosmos DB. It builds on top of *consistent prefix* consistency and offers monotonic reads and writes, read-your-writes, and write-follow-reads. *Session* is the default consistency level. It guarantees that the updated item will be read if the user writes something. 90 | 91 | ### Bounded Staleness consistency 92 | 93 | *Bounded staleness* is the second strongest of consistency models offered in Azure Cosmos DB. It's also built on top of *consistent prefix* consistency. With *bounded staleness* consistency, reads will have some lag behind the writes. The lag can be configured based on two different criteria: the number of K versions of an item or a time interval T. The minimum lag configuration is: 94 | 95 | | Number of regions | Minimum write operations (K) | Minimum time interval (T) | 96 | | ---: | :--- | :--- | 97 | | **Single** | 10 | 5 seconds | 98 | | **Multiple** | 100,000 | 300 seconds (5 minutes) | 99 | 100 | ### Strong consistency 101 | 102 | The strongest consistency model offered by Azure Cosmos DB is *Strong*. This consistency guarantees that reads return the most recent committed data. There are no dirty reads, meaning there's no reading of uncommitted data. There are no nonrepeatable nor phantom reads. Regardless of where the write happens, all regions will serve up the same response to a query. 103 | 104 | ## Data durability 105 | 106 | If there's a region-wide outage, the recovery point objective (RPO)—the amount of time you're able to lose—is tied to the consistency level. The RPO is dependent on the number of regions, the replication mode, and the consistency level. Consider the table below to show how they matter. 107 | 108 | | Consistency level | RPO if region outage | 109 | | ---: | :--- | 110 | | Session, Consistent Prefix, Eventual | < 15 minutes | 111 | | Bounded Staleness | K & T | 112 | | Strong | 0 | 113 | 114 | For more information on consistency levels, see [consistency levels in Azure Cosmos DB](https://docs.microsoft.com/azure/cosmos-db/consistency-levels). 115 | 116 | [Next | Security in Azure Cosmos DB](security.md){: .btn .btn-primary .btn-lg } 117 | -------------------------------------------------------------------------------- /docs/intro-nosql.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: What is NoSQL? 3 | description: Learn how NoSQL databases can efficiently query and serve substantial amounts of semi-structured and unstructured data. 4 | ms.service: cosmos-db 5 | ms.topic: reference 6 | ms.date: 08/19/2022 7 | author: seesharprun 8 | ms.author: sidandrews 9 | ms.reviewer: mjbrown 10 | sequence: 1 11 | --- 12 | 13 | # What is NoSQL? 14 | 15 | The term *NoSQL* was introduced in 2009 and describes a type of non-relational, distributed database. NoSQL databases can efficiently query and serve substantial amounts of semi-structured and unstructured data. Unlike relational databases, NoSQL databases are schema-agnostic. NoSQL databases don't define a specific columnar structure, which allows for greater flexibility, less brittle systems, and support for rapidly changing or unstructured data. 16 | 17 | ![Diagram depicting a relational database schema with an Order and OrderDetails table.](media/intro-nosql/relational_tables.svg) 18 | 19 | In the diagram above, you can see that relational tables have a defined schema. Specific columns and their types represent each table's structure, and relationships are represented via foreign keys. For example, a single **Orders** row may have many **Order Details** rows associated with it. To query this information in its entirety, you must join both tables. 20 | 21 | In stark contrast, the NoSQL document below depicts the same **Order/Order Details** relationship via an internal object array in a single document. 22 | 23 | ```json 24 | { 25 | "orderId": "873sdfs42981", 26 | "orderDate": 1574161910220, 27 | "firstName": "Zhenis", 28 | "lastName": "Omar", 29 | "address": "123 Broad Street", 30 | "city": "Seattle", 31 | "state": "WA", 32 | "postalCode": "92839", 33 | "orderDetails": [ 34 | { 35 | "orderDetailId": "ds23fhjsdk1", 36 | "productId": "sdf2378", 37 | "unitPrice": 7.99, 38 | "quantity": 1 39 | }, 40 | { 41 | "orderDetailId": "zct687786es", 42 | "productId": "d87f98z", 43 | "unitPrice": 4.59, 44 | "quantity": 3 45 | } 46 | ] 47 | } 48 | ``` 49 | 50 | Retrieving a single **Order** and its associated **Order Details** involves the lookup of a single document. 51 | 52 | ## Benefits of NoSQL 53 | 54 | NoSQL databases are open-source, distributed, and non-relational. These characteristics lend themselves to the following benefits: 55 | 56 | * Non-relational allows storage of semi-structured and unstructured data 57 | * Schema-less, which allows flexible data models 58 | * Rapidly adaptive to changing requirements 59 | * Horizontally scalable due to the distributed nature 60 | * Highly available due to the distributed nature 61 | 62 | If you're coming from a relational background and still aren’t sure how NoSQL differs, see [Understanding the differences between NoSQL and relational databases](https://docs.microsoft.com/azure/cosmos-db/relational-nosql). 63 | 64 | ## NoSQL options 65 | 66 | The NoSQL space offers many options. When choosing a NoSQL database system, consider what kind of data you'll work with: 67 | 68 | * Key-value data 69 | * Column-family data 70 | * Document data 71 | * Graph data 72 | * Schema-less JSON 73 | 74 | In this guide, we'll introduce you to Azure Cosmos DB, Microsoft's flagship non-relational database that supports each of these data options. You'll see an application that uses Azure Cosmos DB for NoSQL to work with schema-less JSON. 75 | 76 | ## NoSQL for our scenario 77 | 78 | You'll see the benefits of NoSQL in our Contoso pet store eCommerce example. 79 | 80 | While the data may seem relational, there are cases for non-relational stores. New product information may come from vendors in various formats: structured, semi-structured, or unstructured. You may need to scale your operations for large traffic, such as running sales on an eCommerce site. Reporting on this data may be complicated. 81 | 82 | [Next | Introduction to Azure Cosmos DB](intro-cosmos.md){: .btn .btn-primary .btn-lg } 83 | -------------------------------------------------------------------------------- /docs/media/change-feed-concepts/change-feed-processor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/change-feed-concepts/change-feed-processor.png -------------------------------------------------------------------------------- /docs/media/change-feed-with-cosmos-db-trigger-function/function-app-configuration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/change-feed-with-cosmos-db-trigger-function/function-app-configuration.png -------------------------------------------------------------------------------- /docs/media/change-feed-with-cosmos-db-trigger-function/function-app-monitor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/change-feed-with-cosmos-db-trigger-function/function-app-monitor.png -------------------------------------------------------------------------------- /docs/media/deploy-to-azure-app-service/app-service-configuration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/deploy-to-azure-app-service/app-service-configuration.png -------------------------------------------------------------------------------- /docs/media/event-sourcing/cosmos-db-trigger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/event-sourcing/cosmos-db-trigger.png -------------------------------------------------------------------------------- /docs/media/event-sourcing/event-hubs-instance-overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/event-sourcing/event-hubs-instance-overview.png -------------------------------------------------------------------------------- /docs/media/event-sourcing/function-app-configuration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/event-sourcing/function-app-configuration.png -------------------------------------------------------------------------------- /docs/media/get-started-with-java-and-key-vault/key-vault-access-policies.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/get-started-with-java-and-key-vault/key-vault-access-policies.png -------------------------------------------------------------------------------- /docs/media/get-started-with-java-and-key-vault/select-key-current-version.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/get-started-with-java-and-key-vault/select-key-current-version.png -------------------------------------------------------------------------------- /docs/media/get-started-with-java-and-key-vault/select-key-vault-app-application-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/get-started-with-java-and-key-vault/select-key-vault-app-application-settings.png -------------------------------------------------------------------------------- /docs/media/get-started-with-java-and-key-vault/select-key-vault-app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/get-started-with-java-and-key-vault/select-key-vault-app.png -------------------------------------------------------------------------------- /docs/media/get-started-with-java-and-key-vault/select-key-vault.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/get-started-with-java-and-key-vault/select-key-vault.png -------------------------------------------------------------------------------- /docs/media/get-started-with-java-and-key-vault/select-resource-groups.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/get-started-with-java-and-key-vault/select-resource-groups.png -------------------------------------------------------------------------------- /docs/media/get-started-with-java-and-key-vault/select-show-secret-value.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/get-started-with-java-and-key-vault/select-show-secret-value.png -------------------------------------------------------------------------------- /docs/media/get-started-with-java-and-key-vault/spring-initializr-install.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/get-started-with-java-and-key-vault/spring-initializr-install.png -------------------------------------------------------------------------------- /docs/media/get-started-with-java-and-key-vault/view-key-vault-app-url.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/get-started-with-java-and-key-vault/view-key-vault-app-url.png -------------------------------------------------------------------------------- /docs/media/get-started-with-java-and-key-vault/view-secret-value.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/get-started-with-java-and-key-vault/view-secret-value.png -------------------------------------------------------------------------------- /docs/media/index/cover.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/index/cover.ai -------------------------------------------------------------------------------- /docs/media/migrate-to-azure-spring-apps/azure-spring-apps-config-server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/migrate-to-azure-spring-apps/azure-spring-apps-config-server.png -------------------------------------------------------------------------------- /docs/media/migrate-to-azure-spring-apps/azure-spring-apps-deployment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/migrate-to-azure-spring-apps/azure-spring-apps-deployment.png -------------------------------------------------------------------------------- /docs/media/migrate-to-azure-spring-apps/config-server-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/migrate-to-azure-spring-apps/config-server-settings.png -------------------------------------------------------------------------------- /docs/media/migrate-to-azure-spring-apps/create-service-binding-page-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/migrate-to-azure-spring-apps/create-service-binding-page-settings.png -------------------------------------------------------------------------------- /docs/media/migrate-to-azure-spring-apps/select-add-diagnostic-setting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/migrate-to-azure-spring-apps/select-add-diagnostic-setting.png -------------------------------------------------------------------------------- /docs/media/migrate-to-azure-spring-apps/select-create-service-binding.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/migrate-to-azure-spring-apps/select-create-service-binding.png -------------------------------------------------------------------------------- /docs/media/migrate-to-azure-spring-apps/view-service-binding-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/migrate-to-azure-spring-apps/view-service-binding-page.png -------------------------------------------------------------------------------- /docs/media/mission-critical-situations-for-cosmos-db/backup-and-restore-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/mission-critical-situations-for-cosmos-db/backup-and-restore-settings.png -------------------------------------------------------------------------------- /docs/media/mission-critical-situations-for-cosmos-db/firewall-and-virtual-network-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/mission-critical-situations-for-cosmos-db/firewall-and-virtual-network-settings.png -------------------------------------------------------------------------------- /docs/media/scaling-in-cosmos-db/manual-scale-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/scaling-in-cosmos-db/manual-scale-settings.png -------------------------------------------------------------------------------- /docs/media/scaling-in-cosmos-db/provision-throughput-selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/scaling-in-cosmos-db/provision-throughput-selected.png -------------------------------------------------------------------------------- /docs/media/schema-considerations/contoso-pet-supplies-partitions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/schema-considerations/contoso-pet-supplies-partitions.png -------------------------------------------------------------------------------- /docs/media/schema-considerations/contoso-pet-supplies-relational-database-model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/schema-considerations/contoso-pet-supplies-relational-database-model.png -------------------------------------------------------------------------------- /docs/media/send-notifications-with-azure-logic-apps/search-for-event-hub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/send-notifications-with-azure-logic-apps/search-for-event-hub.png -------------------------------------------------------------------------------- /docs/media/send-notifications-with-azure-logic-apps/search-for-logic-app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/send-notifications-with-azure-logic-apps/search-for-logic-app.png -------------------------------------------------------------------------------- /docs/media/send-notifications-with-azure-logic-apps/select-blank-logic-app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/send-notifications-with-azure-logic-apps/select-blank-logic-app.png -------------------------------------------------------------------------------- /docs/media/send-notifications-with-azure-logic-apps/select-create-resource.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/cloud-scale-data-for-devs-guide/70d8c1189ce8f38a65df864dbd5d8ea530b43042/docs/media/send-notifications-with-azure-logic-apps/select-create-resource.png -------------------------------------------------------------------------------- /docs/mission-critical-situations-for-cosmos-db.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Use Azure Cosmos DB for mission critical situations 3 | description: Learn how to use Azure Cosmos DB for mission critical situations, such as continuous backup and restore. 4 | ms.service: cosmos-db 5 | ms.topic: reference 6 | ms.date: 08/19/2022 7 | author: seesharprun 8 | ms.author: sidandrews 9 | ms.reviewer: mjbrown 10 | sequence: 15 11 | --- 12 | 13 | # Use Azure Cosmos DB for mission critical situations 14 | 15 | Azure Cosmos DB is built for mission critical situations. In addition to being a replicable, globally distributed database system, it has other features that help in mission critical situations: 16 | 17 | - Continuous backup and restore 18 | 19 | - Secure access via firewalls, virtual networks, and private connections 20 | 21 | - Secure data via customer managed keys and client-side encryption 22 | 23 | ## Continuous backup and restore 24 | 25 | Azure Cosmos DB performs data backups without impacting the performance and availability of your databases. Also, it operates without consuming additional RUs. These backups are taken in every region where the account exists. These backups can be used for a point-in-time restoration within the retention period. 26 | 27 | Retention periods are the lowest time value of these two situations: 28 | 29 | - Up to resource creation time 30 | 31 | - 30 days in the past 32 | 33 | Continuous backups are stored in locally redundant storage blobs by default. However, if regions are set up to be zone redundant, then continuous backups are stored in zone redundant storage blobs. 34 | 35 | These settings are configurable in the Azure portal, under the **Backup & Restore** setting for your Azure Cosmos DB account. 36 | 37 | ![Screenshot that shows an Azure Cosmos DB account with Backup and Restore selected.](media/mission-critical-situations-for-cosmos-db/backup-and-restore-settings.png) 38 | 39 | > Restoring always restores into a new account. 40 | 41 | For more information about how to work with continuous backup and restore, see [Continuous backup with point-in-time restore in Azure Cosmos DB](https://docs.microsoft.com/azure/cosmos-db/continuous-backup-restore-introduction). 42 | 43 | ## Secure access to your Azure Cosmos DB account 44 | 45 | Your Azure Cosmos DB account is publicly accessible by default and can be accessed whenever requests have valid authorization tokens. However, you can configure your Azure Cosmos DB account to be more secure. 46 | 47 | ![Screenshot that shows a Azure Cosmos DB account with Firewall and virtual networks selected.](media/mission-critical-situations-for-cosmos-db/firewall-and-virtual-network-settings.png) 48 | 49 | When you view the resource in Azure portal, use these settings to secure your Cosmos DB account: 50 | 51 | - Firewall and virtual networks 52 | 53 | - Private Endpoint Connections 54 | 55 | You can use firewall settings to allow connections from specific IP addresses and CIDR ranges. Note that IP addresses are in IPv4 notation. For more information, see [Configure IP firewall in Azure Cosmos DB](https://docs.microsoft.com/azure/cosmos-db/how-to-configure-firewall). 56 | 57 | You can secure Azure Cosmos DB by placing it on a virtual network for access. Virtual network traffic accesses Azure Cosmos DB via a service endpoint. For more information, see [Configure access to Azure Cosmos DB from virtual networks](https://docs.microsoft.com/azure/cosmos-db/how-to-configure-vnet-service-endpoint). 58 | 59 | Virtual networks that access Azure Cosmos DB work with Azure Private Link. It exposes a private endpoint to a subnet within your virtual network. For more information, see [Configure Azure Private Link for an Azure Cosmos account](https://docs.microsoft.com/azure/cosmos-db/how-to-configure-private-endpoints). 60 | 61 | ## Secure data via additional encryption 62 | 63 | There are multiple ways to manage data access in Azure Cosmos DB: You can use multiple keys, read-only keys, and role-based access control. Data is also secured in other ways. By default, data stored in Azure Cosmos DB is encrypted with service-managed keys, which means you don't need to do anything to configure the first layer of encryption. 64 | 65 | If service-managed keys aren't secure enough, you can use customer-managed keys as a second layer of data encryption. For more information, see [Configure customer-managed keys for your Azure Cosmos account with Azure Key Vault](https://docs.microsoft.com/azure/cosmos-db/how-to-setup-cmk). 66 | 67 | Another Azure Cosmos DB data encryption feature is *Always Encrypted*. This feature supports client-side encryption. Use it when you transmit sensitive data, such as credit card numbers or personal identification numbers, such as national identification numbers. Always Encrypted allows you to set access controls at the property level for stored objects. For more information, see [Use client-side encryption with Always Encrypted for Azure Cosmos DB](https://docs.microsoft.com/azure/cosmos-db/how-to-always-encrypted?tabs=java). 68 | 69 | [Next | Migrate to Azure Spring Apps](migrate-to-azure-spring-apps.md){: .btn .btn-primary .btn-lg } 70 | -------------------------------------------------------------------------------- /docs/scaling-in-cosmos-db.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Scaling in Azure Cosmos DB 3 | description: Learn about scaling in Azure Cosmos DB and the manual and Autoscale options that can be set depending on your workload. 4 | ms.service: cosmos-db 5 | ms.topic: reference 6 | ms.date: 08/19/2022 7 | author: seesharprun 8 | ms.author: sidandrews 9 | ms.reviewer: mjbrown 10 | sequence: 12 11 | --- 12 | 13 | # Scaling in Azure Cosmos DB 14 | 15 | Azure Cosmos DB works with scaling throughput in two ways: provisioned throughput, which is used in the demo, and serverless. 16 | 17 | At the time that you create your database, you must decide whether to use provisioned throughput or serverless scaling. 18 | 19 | ![Screenshot that shows the New Database page with Provision throughput selected.](media/scaling-in-cosmos-db/provision-throughput-selected.png) 20 | 21 | Serverless scalability works well with intermittent workloads, and is coupled with Azure Functions and other [Azure serverless](https://azure.microsoft.com/solutions/serverless/) offerings. With serverless scalability, you pay on a per-hour basis rather than on RU/s. Serverless accounts aren't geo-redundant, as they're limited to one region. 22 | 23 | With provisioned throughput, scale settings are configured at the container level. There are two options for scaling container throughput: 24 | 25 | - Manual 26 | - Autoscale 27 | 28 | The Manual setting for scaling your containers gives you control to set the throughput of the container. This setting works best when for a consistent, steady workload. When you configure a container for manual throughput, you need to set the desired throughput. In our example, we set scaling to 400 RU/s and it consistently stays at 400 RU/s. If the workload gets heavier, we need to adjust the setting manually. 29 | 30 | ![Screenshot that shows the manual scale settings.](media/scaling-in-cosmos-db/manual-scale-settings.png) 31 | 32 | The Autoscale setting works best in cases when traffic ebbs and flows. If you choose Autoscale for your container, you need to specify a maximum number of RU/s for the resource. Your Azure Cosmos DB container can scale from 10% of maximum RU/s to the maximum RU/s. 33 | 34 | ## Learn more 35 | 36 | - [How to choose between provisioned throughput and serverless on Azure Cosmos DB](https://docs.microsoft.com/azure/cosmos-db/throughput-serverless) 37 | 38 | - [How to choose between manual and autoscale on Azure Cosmos DB](https://docs.microsoft.com/azure/cosmos-db/how-to-choose-offer) 39 | 40 | [Next | Bulk executor](bulk-executor.md){: .btn .btn-primary .btn-lg } 41 | -------------------------------------------------------------------------------- /docs/schema-considerations.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Schema design considerations for Azure Cosmos DB 3 | description: Learn about schema design considerations for Azure Cosmos DB. 4 | ms.service: cosmos-db 5 | ms.topic: reference 6 | ms.date: 08/19/2022 7 | author: seesharprun 8 | ms.author: sidandrews 9 | ms.reviewer: mjbrown 10 | sequence: 14 11 | --- 12 | 13 | # Schema design considerations for Azure Cosmos DB 14 | 15 | Azure Cosmos DB stores data as schema-less JSON objects. The schema you intend to use needs to be managed or enforced by outside applications. 16 | 17 | There are decisions in your Azure Cosmos DB design that need to be made before you create the database. Consider the following points when you create JSON objects: 18 | 19 | - Data modeling 20 | 21 | - Partition key 22 | 23 | ## Data modeling 24 | 25 | Before you store data, make sure your objects are stored in a logical way. 26 | 27 | In a nonrelational database, data is stored denormalized and is optimized for queries and writes. 28 | 29 | Consider the Contoso Pet Supplies models in a relational entity relationship diagram: 30 | 31 | ![Diagram that shows the Contoso Pet Supplies relational database model.](media/schema-considerations/contoso-pet-supplies-relational-database-model.png) 32 | 33 | Notice that tables are organized by entities, and bridge tables are present to establish relationships between entities. 34 | 35 | When you create documents for Azure Cosmos DB, consider the following questions: 36 | 37 | - How is this data accessed? 38 | 39 | - Are columns called together frequently in queries? 40 | 41 | - Are columns called together frequently in queries via JOINs? Keep in mind that the relational concept of JOINs doesn't translate to the JOIN in Azure Cosmos DB. 42 | 43 | - Are columns updated together? 44 | 45 | Sometimes entities translate 1-to-1 from relational to nonrelational. At other times, you'll find that it makes more sense to embed entities. This scenario can occur when you embed the manufacturer within a product. For example, if you don't use the manufacturer alone but use it only when you work with products. When you need to use JOINs in relational queries, you might need to denormalize the data. For example, when you pass along customer emails for wishlist notifications. The reason is because wishlist updates need to go to the customer. 46 | 47 | This article gives guidance on [Modeling data in Azure Cosmos DB](https://docs.microsoft.com/azure/cosmos-db/sql/modeling-data). 48 | 49 | ## Partition key decisions 50 | 51 | The partition key stores objects of the same value together in the partition key. For example, if you want to categorize your products, you could store them in a separate container and partition them by category. Doing so would store products of the same category together in a logical partition. When determining what to use for the partition key, keep this guidance in mind: 52 | 53 | - For read-heavy containers, use a field that is optimized for frequently run queries. 54 | - For write-heavy containers, use a field with diverse data that balances the load. 55 | 56 | When looking at models in the Contoso Pet Supplies project, we create a property called `documentType` to use as the partition key. A couple of exercises bring us to that decision: 57 | 58 | - We first look at our data to see what details are stored in our objects. If they all have to live in one container, what would the queries look like? There would be many queries filtered by object type. 59 | 60 | - We then view our data for how it loads in the database. The object type needs to be diverse enough to balance the load across partitions. It needs to ensure each value has a similar load and that no single value takes on a heavy load. 61 | 62 | By setting `/documentType` as our partition key, we have a key that works well for our environment. 63 | 64 | ![Diagram showing the Contoso Pet Supplies partitions.](media/schema-considerations/contoso-pet-supplies-partitions.png) 65 | 66 | ## Additional references 67 | 68 | - [Partition Strategy - Azure Cosmos DB Essentials Season 2 (YouTube)](https://www.youtube.com/watch?v=QLgK8yhKd5U) 69 | 70 | - [Schema Design Strategy - Azure Cosmos DB Essentials Season 2 (YouTube)](https://www.youtube.com/watch?v=bKDaL-GRSAM) 71 | 72 | [Next | Azure Cosmos DB for mission critical situations](mission-critical-situations-for-cosmos-db.md){: .btn .btn-primary .btn-lg } 73 | -------------------------------------------------------------------------------- /docs/security.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Security in Azure Cosmos DB 3 | description: Learn how you can implement security in Azure Cosmos DB using role-based access control or keys. 4 | ms.service: cosmos-db 5 | ms.topic: reference 6 | ms.date: 08/19/2022 7 | author: seesharprun 8 | ms.author: sidandrews 9 | ms.reviewer: mjbrown 10 | sequence: 3 11 | --- 12 | 13 | # Security in Azure Cosmos DB 14 | 15 | Security is a critical concern for any system. Azure Cosmos DB offers various options for keeping your data safe and for controlling who can access it. 16 | 17 | ## Access data with keys 18 | 19 | Your Azure Cosmos DB account contains a set of keys for *read-write* access and a set of *read only* keys. If you're developing with keys, you need to secure those credentials so that they don't accidentally make it into source control. This guide outlines options for controlling keys rather than storing key values in `application.properties`. 20 | 21 | If you must work with keys: 22 | 23 | * Store the keys in environment variables. Environment variables make it easy to store the values in a place without checking them in to source control. [Azure App Service](https://docs.microsoft.com/azure/app-service/), [Azure Functions](https://docs.microsoft.com/azure/azure-functions/), and [Azure Spring Apps](https://docs.microsoft.com/azure/spring-apps/) support environment variables as well. 24 | 25 | * Another option for storing secure values is in [Azure Key Vault](https://docs.microsoft.com/azure/key-vault/). For more information on working with Java and Azure Key Vault, check out our [Hello World code sample with Java and Azure Key Vault](get-started-with-java-and-key-vault.md). 26 | 27 | ## Role-based access control 28 | 29 | One of the ways you can secure access to your Azure Cosmos DB account is with [role-based access control (RBAC)](https://docs.microsoft.com/azure/role-based-access-control/overview). With Azure RBAC, you can assign users, service principals, managed identities, and groups as members within a role. Azure RBAC can be managed in the section labeled **Access Control (IAM)** when working in the Azure portal. IAM is an acronym for Identity and Access Management. 30 | 31 | Azure RBAC uses [Azure Active Directory (Azure AD)](https://azure.microsoft.com/services/active-directory/) for the authentication portion. It uses role assignments for authorization determination. By assigning roles at the resource level, you have fine-grained control over your resource access. 32 | 33 | ### Azure Cosmos DB-specific RBAC roles 34 | 35 | Azure Cosmos DB uses two built-in roles. The **Cosmos DB Built-in Data Reader** role includes actions for reading metadata on database accounts, reading items in a container, executing queries, and reading the change feed. The **Cosmos DB Built-in Data Contributor** role includes actions for reading metadata on database accounts, reading and writing with containers, and reading and writing with items. 36 | 37 | There are no built-in Azure Cosmos DB-specific roles for: 38 | 39 | * Creating, replacing, and deleting databases and containers. 40 | * Replacing container throughput. 41 | * Creating, replacing, deleting, and reading stored procedures, triggers, and user defined functions. 42 | 43 | ### Custom RBAC roles 44 | 45 | Azure Cosmos DB actions support wildcard notation at the container and item levels when creating custom role definitions for RBAC. Their actions can be referred to as: 46 | 47 | * `Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*` 48 | * `Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*` 49 | 50 | There are three scopes for role assignments: 51 | 52 | * Account level (`/`) 53 | * Database level (`/dbs/`) 54 | * Container level (`/dbs//colls/`) 55 | 56 | ## Using RBAC alone 57 | 58 | You can configure Azure Cosmos DB to use only RBAC and not allow the use of primary and secondary keys. Using RBAC alone can be done as part of creating or updating your Azure Cosmos DB account by using Azure Resource Manager templates, then setting the `disableLocalAuth` property to *true*. 59 | 60 | ## Managed identities 61 | 62 | You can use a managed identity for authentication purposes between Azure resources. Services that support managed identities for Azure resources include Azure App Service, Azure Spring Apps, Azure Logic Apps, and Azure Functions. For a comprehensive list of services that support managed identities, see [what Azure services support managed identity](https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview#what-azure-services-support-the-feature). These services are used throughout this guide. Rather than having to rely on keys, you can use managed identities to grant roles via RBAC. When you create a managed identity, it lives with the resource. When the resource is deleted, the managed identity is also deleted. 63 | 64 | Suppose a microservice runs in Azure Spring Apps. The microservice wants to write to Azure Cosmos DB and needs the key. You can grant the managed identity access to read the keys via the Cosmos DB Account Reader role. Managed identities are seen on the screen for RBAC. 65 | 66 | ## Azure Key Vault 67 | 68 | When working in applications, you may be tempted to store key information in `application.properties`. However, if this file gets checked into source control, anyone who has access to your source code can access your key. Rather than running the risk of exposing credentials, you should store them securely in Azure Key Vault. When storing values in Azure Key Vault, you can use either vault access policies or secure things via RBAC. You can grant permissions to users, service principals, managed identities, and groups. 69 | 70 | ## Networking security 71 | 72 | Another approach to securing Azure Cosmos DB is through networking. Options include: 73 | 74 | * [IP firewall](https://docs.microsoft.com/azure/cosmos-db/how-to-configure-firewall) 75 | * [Virtual network support](https://docs.microsoft.com/azure/cosmos-db/how-to-configure-vnet-service-endpoint) 76 | * [Private endpoints using Azure Private Link](https://docs.microsoft.com/azure/cosmos-db/how-to-configure-private-endpoints) 77 | 78 | ## Encrypting data 79 | 80 | Data stored in Azure Cosmos DB is automatically encrypted with service-managed keys. Service-managed keys are keys maintained by Microsoft. If you want to add another layer of encryption, you can bring your own customer-managed keys. These keys must be stored in Azure Key Vault. Customer-managed keys must be configured during account creation. There are no extra charges for enabling the feature for your own customer-managed key; however, there may be an increase in processor usage for encryption and decryption. This cost will be seen in the RU (Request Units) cost. 81 | 82 | For more information about setting up customer-managed keys, see [configure customer-managed keys](https://docs.microsoft.com/azure/cosmos-db/how-to-setup-cmk). 83 | 84 | Azure Cosmos DB backs up your data. If you need to restore this data with a customer-managed key, the encryption key must be available in Azure Key Vault. 85 | 86 | [Next | Get started with Java and Azure Key Vault](get-started-with-java-and-key-vault.md){: .btn .btn-primary .btn-lg } 87 | -------------------------------------------------------------------------------- /docs/send-notifications-with-azure-logic-apps.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Use send notifications with Azure Logic Apps 3 | description: Learn how to send notifications with Azure Logic Apps to notify users when products are updated. 4 | ms.service: cosmos-db 5 | ms.topic: reference 6 | ms.date: 08/19/2022 7 | author: seesharprun 8 | ms.author: sidandrews 9 | ms.reviewer: mjbrown 10 | sequence: 11 11 | --- 12 | 13 | # Send notifications with Azure Logic Apps 14 | 15 | In the following sample app, we notify users when products are updated. We use *Azure Logic Apps* to automate this process. 16 | 17 | [Azure Logic Apps](https://docs.microsoft.com/azure/logic-apps/) handle automations that integrate systems, services, apps, and data. They move data around, send notifications, monitor data sources, and connect with other services through connectors. 18 | 19 | Logic app capabilities include: 20 | 21 | - Sending email when an event occurs 22 | 23 | - Monitoring business reviews, analyzing review content, and sending notifications based on outcomes 24 | 25 | - Data cleansing pipelines and data migration 26 | 27 | - Integrating APIs and external systems 28 | 29 | The following example is built from the chain that we started with our Azure Cosmos DB triggered Azure Function. The Azure Function sends data to Azure Event Hubs. Our logic app monitors Azure Event Hubs notifications and emails us when products are updated. 30 | 31 | ## Create a logic app 32 | 33 | 1. In the Azure portal, select **Create a resource**. 34 | 35 | ![Screenshot that shows the Azure portal Home page with Create a resource group highlighted.](media/send-notifications-with-azure-logic-apps/select-create-resource.png) 36 | 37 | 1. Search for *logic app*, and then select the **Logic App**. 38 | 39 | ![Screenshot that shows logic app search results on the Marketplace page.](media/send-notifications-with-azure-logic-apps/search-for-logic-app.png) 40 | 41 | 1. Select **Create**. 42 | 43 | 1. On the **Create Logic App** page, enter the following settings: 44 | 45 | - **Resource Group**: *pet-supplies-demo-rg* 46 | - **Logic App name**: *pet-supplies-wishlist-notice* 47 | - **Publish**: **Workflow** 48 | - **Region**: \ 49 | - **Plan type**: **Consumption** 50 | 51 | 1. Select **Review + create**, then select **Create**. 52 | 53 | ## Build the logic app 54 | 55 | 1. After the logic app is created, navigate to the resource, which loads **Logic App Designer**. Select **Blank Logic App**. 56 | 57 | ![Screenshot that shows the Templates page with Blank Logic App selected.](media/send-notifications-with-azure-logic-apps/select-blank-logic-app.png) 58 | 59 | 1. For the first task, search for *event hub* and then select the trigger **When events are available in Event Hub**. 60 | 61 | ![Screenshot that shows event hub search.](media/send-notifications-with-azure-logic-apps/search-for-event-hub.png) 62 | 63 | 1. Give your connection a name. For **Connection String**, set it to the value 64 | you used in AZURE_EVENT_HUB_CONNECTION. Then, select **Create**. 65 | 66 | 1. After the step connects to the event hub, enter the following settings: 67 | 68 | - **Event Hub name**: *pet-supplies-events* 69 | - **Content type**: **application/json** 70 | - **Consumer group name**: *$Default* 71 | 72 | 1. Add a new step. 73 | 74 | 1. Search for *Send an Email (V2) Outlook*. 75 | 76 | 1. Sign in with your Office 365 credentials. 77 | 78 | 1. Enter your email address in the **To** list. 79 | 80 | 1. For the subject, use *Contoso Product Update*. 81 | 82 | 1. For the body, use: *The following product is updated:*. 83 | 84 | 1. Add **Content** from the **Dynamic content** dialog. 85 | 86 | 1. Select **Save**. 87 | 88 | 1. As a test, make changes to Pet Supplies products and verify that events were added to the event hub. 89 | 90 | 1. Select **Run Trigger**, then **Run**. 91 | 92 | ## Learn more 93 | 94 | - [Overview for Azure Logic Apps - Azure Logic Apps](https://docs.microsoft.com/azure/logic-apps/logic-apps-overview) 95 | 96 | - [Integration and automation platform options in Azure](https://docs.microsoft.com/azure/azure-functions/functions-compare-logic-apps-ms-flow-webjobs) 97 | 98 | [Next | Scaling in Azure Cosmos DB](scaling-in-cosmos-db.md){: .btn .btn-primary .btn-lg } 99 | --------------------------------------------------------------------------------