From d8bdf647461200941e371a16abf3f56194e62c74 Mon Sep 17 00:00:00 2001 From: Bhaskar Mallapragada Date: Wed, 9 Sep 2020 21:43:49 -0700 Subject: [PATCH] Updating user agent and adding query annotation snippets to readme (#14998) * - Updating user agent as per the guidelines. - Adding query annotation snippets to readme. * readme changes --- .../azure-spring-data-cosmos-core/README.md | 70 ++++++++++++++----- .../azure/spring/data/cosmos/Constants.java | 3 +- .../spring/data/cosmos/CosmosFactory.java | 2 +- ...riesUserReactiveRepositoryCodeSnippet.java | 20 ++++++ ...tatedQueriesUserRepositoryCodeSnippet.java | 17 +++++ .../data/cosmos/CosmosFactoryTestIT.java | 2 +- 6 files changed, 95 insertions(+), 19 deletions(-) create mode 100644 sdk/cosmos/azure-spring-data-cosmos-core/src/samples/java/com/azure/spring/data/cosmos/AnnotatedQueriesUserReactiveRepositoryCodeSnippet.java create mode 100644 sdk/cosmos/azure-spring-data-cosmos-core/src/samples/java/com/azure/spring/data/cosmos/AnnotatedQueriesUserRepositoryCodeSnippet.java diff --git a/sdk/cosmos/azure-spring-data-cosmos-core/README.md b/sdk/cosmos/azure-spring-data-cosmos-core/README.md index eefb47653384b..317615a80ecfd 100644 --- a/sdk/cosmos/azure-spring-data-cosmos-core/README.md +++ b/sdk/cosmos/azure-spring-data-cosmos-core/README.md @@ -27,7 +27,7 @@ SLF4J is only needed if you plan to use logging, please also download an SLF4J b - Azure-spring-data-cosmos also supports `Response Diagnostics String` and `Query Metrics`. Set `queryMetricsEnabled` flag to true in application.properties to enable query metrics. In addition to setting the flag, implement `ResponseDiagnosticsProcessor` to log diagnostics information. - + ```java @Configuration @@ -93,7 +93,7 @@ public class AppConfiguration extends AbstractCosmosConfiguration { ``` ### Customizing Configuration You can customize `DirectConnectionConfig` or `GatewayConnectionConfig` or both and provide them to `CosmosClientBuilder` bean to customize `CosmosAsyncClient` - + ```java @Bean @@ -126,7 +126,7 @@ Use it to annotate your Configuration class to scan a different root package by - Containers will be created automatically unless you don't want them to. Set `autoCreateContainer` to false in `@Container` annotation to disable auto creation of containers. - Note: By default request units assigned to newly created containers is 400. Specify different ru value to customize request units for the container created by the SDK (minimum RU value is 400). - + ```java @Container(containerName = "myContainer", ru = "400") public class User { @@ -182,7 +182,7 @@ public class User { - Annotation `@Container(containerName="myContainer")` specifies container name in Azure Cosmos DB. - Annotation `@PartitionKey` on `lastName` field specifies this field as partition key in Azure Cosmos DB. - + ```java @Container(containerName = "myContainer") public class UserSample { @@ -194,7 +194,7 @@ public class UserSample { ### Create repositories Extends CosmosRepository interface, which provides Spring Data repository support. - + ```java @Repository @@ -206,9 +206,45 @@ public interface UserRepository extends CosmosRepository { - `findByFirstName` method is custom query method, it will find items per firstName. +#### Using annotated queries in repositories +Azure spring data cosmos supports specifying annotated queries in the repositories using `@Query`. +- Examples for annotated queries in synchronous CosmosRepository: + + +```java +public interface AnnotatedQueriesUserRepositoryCodeSnippet extends CosmosRepository { + @Query(value = "select * from c where c.firstName = @firstName and c.lastName = @lastName") + List getUsersByTitleAndValue(@Param("firstName") int firstName, @Param("lastName") String lastName); + + @Query(value = "select * from c offset @offset limit @limit") + List getUsersWithOffsetLimit(@Param("offset") int offset, @Param("limit") int limit); +} +``` + +- Examples for annotated queries in ReactiveCosmosRepository. + + +```java +public interface AnnotatedQueriesUserReactiveRepositoryCodeSnippet extends ReactiveCosmosRepository { + @Query(value = "select * from c where c.firstName = @firstName and c.lastName = @lastName") + Flux getUsersByTitleAndValue(@Param("firstName") int firstName, @Param("lastName") String lastName); + + @Query(value = "select * from c offset @offset limit @limit") + Flux getUsersWithOffsetLimit(@Param("offset") int offset, @Param("limit") int limit); + + @Query(value = "select count(c.id) as num_ids, c.lastName from c group by c.lastName") + Flux getCoursesGroupByDepartment(); +} +``` + +The queries that are specified in the annotation are same as the cosmos queries. +Please refer to the following articles for more information on sql queries in cosmos + - [sql-query-getting-started] [sql_queries_getting_started] + - [tutorial-query-sql-api] [sql_queries_in_cosmos] + ### Create an Application class Here create an application class with all the components - + ```java @SpringBootApplication @@ -266,7 +302,7 @@ public class SampleApplication implements CommandLineRunner { - set name of this field to `id`, this field will be mapped to Item `id` in Azure Cosmos DB. - Supports auto generation of string type UUIDs using the @GeneratedValue annotation. The id field of an entity with a string type id can be annotated with `@GeneratedValue` to automatically generate a random UUID prior to insertion. - + ```java public class GeneratedIdEntity { @@ -280,7 +316,7 @@ public class SampleApplication implements CommandLineRunner { By default, container name will be class name of user domain class. To customize it, add the `@Container(containerName="myCustomContainerName")` annotation to the domain class. The container field also supports SpEL expressions (eg. `container = "${dynamic.container.name}"` or `container = "#{@someBean.getContainerName()}"`) in order to provide container names programmatically/via configuration properties. - Custom IndexingPolicy By default, IndexingPolicy will be set by azure service. To customize it add annotation `@CosmosIndexingPolicy` to domain class. This annotation has 4 attributes to customize, see following: - + ```java // Indicate if indexing policy use automatic or not // Default value is true @@ -306,7 +342,7 @@ String[] excludePaths() default {}; - Azure-spring-data-cosmos supports Optimistic Locking for specific containers, which means upserts/deletes by item will fail with an exception in case the item is modified by another process in the meanwhile. - To enable Optimistic Locking for a container, just create a string `_etag` field and mark it with the `@Version` annotation. See the following: - + ```java @Container(containerName = "myContainer") public class MyItem { @@ -322,7 +358,7 @@ public class MyItem { - Supports [Spring Data pageable and sort](https://docs.spring.io/spring-data/commons/docs/current/reference/html/#repositories.special-parameters). - Based on available RUs on the database account, cosmosDB can return items less than or equal to the requested size. - Due to this variable number of returned items in every iteration, user should not rely on the totalPageSize, and instead iterating over pageable should be done in this way. - + ```java private List findAllWithPageSize(int pageSize) { @@ -342,7 +378,7 @@ private List findAllWithPageSize(int pageSize) { - Azure-spring-data-cosmos supports [spring-boot-starter-data-rest](https://projects.spring.io/spring-data-rest/). - Supports List and nested type in domain class. - Configurable ObjectMapper bean with unique name `cosmosObjectMapper`, only configure customized ObjectMapper if you really need to. e.g., - + ```java @Bean(name = "cosmosObjectMapper") public ObjectMapper objectMapper() { @@ -354,7 +390,7 @@ public ObjectMapper objectMapper() { - Azure-spring-data-cosmos supports auditing fields on database entities using standard spring-data annotations. - This feature can be enabled by adding `@EnableCosmosAuditing` annotation to your application configuration. - Entities can annotate fields using `@CreatedBy`, `@CreatedDate`, `@LastModifiedBy` and `@LastModifiedDate`. These fields will be updated automatically. - + ```java @Container(containerName = "myContainer") public class AuditableUser { @@ -395,7 +431,7 @@ azure.cosmos.secondary.populateQueryMetrics=if-populate-query-metrics - The `@EnableReactiveCosmosRepositories` or `@EnableCosmosRepositories` support user-define the cosmos template, use `reactiveCosmosTemplateRef` or `cosmosTemplateRef` to config the name of the `ReactiveCosmosTemplate` or `CosmosTemplate` bean to be used with the repositories detected. - If you have multiple cosmos database accounts, you can define multiple `CosmosAsyncClient`. If the single cosmos account has multiple databases, you can use the same `CosmosAsyncClient` to initialize the cosmos template. - + ```java @Configuration @@ -500,7 +536,7 @@ public class DatabaseConfiguration extends AbstractCosmosConfiguration { - In the above example, we have two cosmos account, each account has two databases. For each account, we can use the same Cosmos Client. You can create the `CosmosAsyncClient` like this: - + ```java @Bean("secondaryCosmosAsyncClient") @@ -511,7 +547,7 @@ public CosmosAsyncClient getCosmosAsyncClient(CosmosClientBuilder secondaryCosmo - Besides, if you want to define `queryMetricsEnabled` or `ResponseDiagnosticsProcessor` , you can create the `CosmosConfig` for your cosmos template. - + ```java @Bean("secondaryCosmosConfig") @@ -525,7 +561,7 @@ public CosmosConfig getCosmosConfig() { - Create an Application class - + ```java @SpringBootApplication @@ -647,5 +683,7 @@ or contact [opencode@microsoft.com][coc_contact] with any additional questions o [address_repository_it_test]: https://github.com/Azure/azure-sdk-for-java/blob/master/sdk/cosmos/azure-spring-data-cosmos-test/src/test/java/com/azure/spring/data/cosmos/repository/integration/AddressRepositoryIT.java [azure_spring_data_cosmos_docs]: https://docs.microsoft.com/azure/cosmos-db/sql-api-sdk-java-spring-v3 [spring_data_custom_query]: https://docs.spring.io/spring-data/commons/docs/current/reference/html/#repositories.query-methods.details +[sql_queries_in_cosmos]: https://docs.microsoft.com/en-us/azure/cosmos-db/tutorial-query-sql-api +[sql_queries_getting_started]: https://docs.microsoft.com/en-us/azure/cosmos-db/sql-query-getting-started ![Impressions](https://azure-sdk-impressions.azurewebsites.net/api/impressions/azure-sdk-for-java%2Fsdk%2Fcosmos%2F%2Fazure-spring-data-cosmos-core%2FREADME.png) diff --git a/sdk/cosmos/azure-spring-data-cosmos-core/src/main/java/com/azure/spring/data/cosmos/Constants.java b/sdk/cosmos/azure-spring-data-cosmos-core/src/main/java/com/azure/spring/data/cosmos/Constants.java index 0e6cf5fb266da..8b03ad2f938bc 100644 --- a/sdk/cosmos/azure-spring-data-cosmos-core/src/main/java/com/azure/spring/data/cosmos/Constants.java +++ b/sdk/cosmos/azure-spring-data-cosmos-core/src/main/java/com/azure/spring/data/cosmos/Constants.java @@ -22,7 +22,8 @@ public final class Constants { public static final String COSMOS_MODULE_NAME = "cosmos"; public static final String COSMOS_MODULE_PREFIX = "cosmos"; - public static final String USER_AGENT_SUFFIX = "spring-data/"; + private static final String AZURE_SPRING_DATA_COSMOS = "az-sd-cos"; + public static final String USER_AGENT_SUFFIX = AZURE_SPRING_DATA_COSMOS + "/"; public static final String OBJECT_MAPPER_BEAN_NAME = "cosmosObjectMapper"; public static final String AUDITING_HANDLER_BEAN_NAME = "cosmosAuditingHandler"; diff --git a/sdk/cosmos/azure-spring-data-cosmos-core/src/main/java/com/azure/spring/data/cosmos/CosmosFactory.java b/sdk/cosmos/azure-spring-data-cosmos-core/src/main/java/com/azure/spring/data/cosmos/CosmosFactory.java index 3408e72249da0..51721280b8471 100644 --- a/sdk/cosmos/azure-spring-data-cosmos-core/src/main/java/com/azure/spring/data/cosmos/CosmosFactory.java +++ b/sdk/cosmos/azure-spring-data-cosmos-core/src/main/java/com/azure/spring/data/cosmos/CosmosFactory.java @@ -26,7 +26,7 @@ public class CosmosFactory { Constants.USER_AGENT_SUFFIX + PropertyLoader.getProjectVersion(); private static String getUserAgentSuffix() { - return ";" + USER_AGENT_SUFFIX; + return USER_AGENT_SUFFIX; } /** diff --git a/sdk/cosmos/azure-spring-data-cosmos-core/src/samples/java/com/azure/spring/data/cosmos/AnnotatedQueriesUserReactiveRepositoryCodeSnippet.java b/sdk/cosmos/azure-spring-data-cosmos-core/src/samples/java/com/azure/spring/data/cosmos/AnnotatedQueriesUserReactiveRepositoryCodeSnippet.java new file mode 100644 index 0000000000000..d7bfea46e6688 --- /dev/null +++ b/sdk/cosmos/azure-spring-data-cosmos-core/src/samples/java/com/azure/spring/data/cosmos/AnnotatedQueriesUserReactiveRepositoryCodeSnippet.java @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.spring.data.cosmos; + +import com.azure.spring.data.cosmos.repository.Query; +import com.azure.spring.data.cosmos.repository.ReactiveCosmosRepository; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.springframework.data.repository.query.Param; +import reactor.core.publisher.Flux; + +public interface AnnotatedQueriesUserReactiveRepositoryCodeSnippet extends ReactiveCosmosRepository { + @Query(value = "select * from c where c.firstName = @firstName and c.lastName = @lastName") + Flux getUsersByTitleAndValue(@Param("firstName") int firstName, @Param("lastName") String lastName); + + @Query(value = "select * from c offset @offset limit @limit") + Flux getUsersWithOffsetLimit(@Param("offset") int offset, @Param("limit") int limit); + + @Query(value = "select count(c.id) as num_ids, c.lastName from c group by c.lastName") + Flux getCoursesGroupByDepartment(); +} diff --git a/sdk/cosmos/azure-spring-data-cosmos-core/src/samples/java/com/azure/spring/data/cosmos/AnnotatedQueriesUserRepositoryCodeSnippet.java b/sdk/cosmos/azure-spring-data-cosmos-core/src/samples/java/com/azure/spring/data/cosmos/AnnotatedQueriesUserRepositoryCodeSnippet.java new file mode 100644 index 0000000000000..e8671ce8d8816 --- /dev/null +++ b/sdk/cosmos/azure-spring-data-cosmos-core/src/samples/java/com/azure/spring/data/cosmos/AnnotatedQueriesUserRepositoryCodeSnippet.java @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.spring.data.cosmos; + +import com.azure.spring.data.cosmos.repository.CosmosRepository; +import com.azure.spring.data.cosmos.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; + +public interface AnnotatedQueriesUserRepositoryCodeSnippet extends CosmosRepository { + @Query(value = "select * from c where c.firstName = @firstName and c.lastName = @lastName") + List getUsersByTitleAndValue(@Param("firstName") int firstName, @Param("lastName") String lastName); + + @Query(value = "select * from c offset @offset limit @limit") + List getUsersWithOffsetLimit(@Param("offset") int offset, @Param("limit") int limit); +} diff --git a/sdk/cosmos/azure-spring-data-cosmos-test/src/test/java/com/azure/spring/data/cosmos/CosmosFactoryTestIT.java b/sdk/cosmos/azure-spring-data-cosmos-test/src/test/java/com/azure/spring/data/cosmos/CosmosFactoryTestIT.java index 59bad6c9bfbf5..2cd58294af61b 100644 --- a/sdk/cosmos/azure-spring-data-cosmos-test/src/test/java/com/azure/spring/data/cosmos/CosmosFactoryTestIT.java +++ b/sdk/cosmos/azure-spring-data-cosmos-test/src/test/java/com/azure/spring/data/cosmos/CosmosFactoryTestIT.java @@ -67,7 +67,7 @@ public void testConnectionPolicyUserAgentKept() throws IllegalAccessException { CosmosFactory.createCosmosAsyncClient(cosmosClientBuilder); final String uaSuffix = getUserAgentSuffixValue(cosmosClientBuilder); - assertThat(uaSuffix).contains("spring-data"); + assertThat(uaSuffix).contains(Constants.USER_AGENT_SUFFIX); } private String getUserAgentSuffixValue(CosmosClientBuilder cosmosClientBuilder) throws IllegalAccessException {