Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion eng/pipelines/templates/stages/cosmos-sdk-client.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ stages:
ServiceDirectory: cosmos
Artifacts: ${{ parameters.Artifacts }}
AdditionalModules: ${{ parameters.AdditionalModules }}
ACCOUNT_HOST: 'https://localhost:8081/'
ACCOUNT_KEY: 'C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=='
SECONDARY_ACCOUNT_KEY: 'C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=='
# Increased timeout to 90 because of cosmos emulator taking 25-30 mins to download emulator
# Issue filed to improve download speed: https://github.com/Azure/azure-sdk-for-java/issues/12970
TimeoutInMinutes: 90
Expand All @@ -106,7 +109,7 @@ stages:
JavaTestVersion: '1.8'
ProfileFlag: '-P integration-test-emulator'
DisplayName: 'Spring Emulator only Integration Tests'
AdditionalArgs: '-DargLine="-DACCOUNT_HOST=https://localhost:8081/ -DACCOUNT_KEY=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw== -DSECONDARY_ACCOUNT_KEY=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="'
AdditionalArgs: '-DargLine="-DACCOUNT_HOST=https://localhost:8081/ -DACCOUNT_KEY=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw== -DSECONDARY_ACCOUNT_KEY=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw== -DNEW_ACCOUNT_HOST=https://localhost:8081/ -DNEW_ACCOUNT_KEY=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw== -DNEW_SECONDARY_ACCOUNT_KEY=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we look at defining variables for these keys and using those in the additional args instead this really, really long inline expansion?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kushagraThapar @JimSuplizio Can you tell me how to define variables for these keys here? I defined these variables as template parameters, but it fails to parse these variables

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zhoufenqin - Had a discussion with @JimSuplizio on this, it seems like it is not possible to pass parameters to archetype-sdk-tests.yml - without changing the archetype-sdk-tets.yml - which we don't plan to do now. So I expanded these back like the way they were before.

Encryption_Integration_Tests_Java8:
OSVmImage: 'windows-2019'
JavaTestVersion: '1.8'
Expand Down
9 changes: 8 additions & 1 deletion sdk/cosmos/azure-spring-data-cosmos/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,22 @@ mvn clean install -Dgpg.skip
- Click Databases, and then click Azure Cosmos DB to create your database.
- Navigate to the database you have created, and click Access keys and copy your URI and access keys for your database.

2. Set environment variables ACCOUNT_HOST, ACCOUNT_KEY and SECONDARY_ACCOUNT_KEY, where value of them are Cosmos account URI, primary key and secondary key.
2. Set environment variables ACCOUNT_HOST, ACCOUNT_KEY and SECONDARY_ACCOUNT_KEY, where value of them are Cosmos account URI, primary key and secondary key.

`azure-spring-data-cosmos` also support multiple database configuration. So set the second group environment variables NEW_ACCOUNT_HOST, NEW_ACCOUNT_KEY and NEW_SECONDARY_ACCOUNT_KEY, the two group environment variables can be same.
3. Run maven command with `integration-test-azure` profile.

```bash
set ACCOUNT_HOST=your-cosmos-account-uri
set ACCOUNT_KEY=your-cosmos-account-primary-key
set SECONDARY_ACCOUNT_KEY=your-cosmos-account-secondary-key

set NEW_ACCOUNT_HOST=your-cosmos-account-uri
set NEW_ACCOUNT_KEY=your-cosmos-account-primary-key
set NEW_SECONDARY_ACCOUNT_KEY=your-cosmos-account-secondary-key
mvnw -P integration-test-azure clean install
```

- on Emulator

Setup Azure Cosmos DB Emulator by following [this instruction](https://docs.microsoft.com/azure/cosmos-db/local-emulator), and set associated environment variables. Then run test with:
Expand Down
137 changes: 137 additions & 0 deletions sdk/cosmos/azure-spring-data-cosmos/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,143 @@ public class SampleApplication implements CommandLineRunner {
```
Autowired UserRepository interface, then can do save, delete and find operations. Spring Data Azure Cosmos DB uses the CosmosTemplate to execute the queries behind *find*, *save* methods. You can use the template yourself for more complex queries.

## Support multi-database configuration
The `azure-spring-data-cosmos` support multi-database configuration, here is a sample to config multiple account database

### Add the dependency
[//]: # ({x-version-update-start;com.azure:azure-spring-data-cosmos;current})
```xml
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is missing the update tags. You'll want to add the following before the XML start code tag
[//]: # ({x-version-update-start;com.azure:azure-spring-data-cosmos;current})
and then add the following after the XML end code tag
[//]: # ({x-version-update-end})

The way the tags are formatted they won't show up unless looking at the raw readme. The version tools use the tags for updating.

<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-spring-data-cosmos</artifactId>
<version>3.0.0-beta.1</version>
</dependency>
```
[//]: # ({x-version-update-end})

### Config application properties
The example uses the `application.properties` file
```properties
azure.cosmos.primary.uri=your-primary-cosmosDb-uri
azure.cosmos.primary.key=your-primary-cosmosDb-key
azure.cosmos.primary.secondaryKey=your-primary-cosmosDb-secondary-key
azure.cosmos.primary.database=your-primary-cosmosDb-dbName
azure.cosmos.primary.populateQueryMetrics=if-populate-query-metrics

azure.cosmos.secondary.uri=your-secondary-cosmosDb-uri
azure.cosmos.secondary.key=your-secondary-cosmosDb-key
azure.cosmos.secondary.secondaryKey=your-secondary-cosmosDb-secondary-key
azure.cosmos.secondary.database=your-secondary-cosmosDb-dbName
azure.cosmos.secondary.populateQueryMetrics=if-populate-query-metrics
```

### Define Entities and Repositories
The [Entity](https://github.com/Azure/azure-sdk-for-java/tree/master/sdk/cosmos/azure-spring-data-cosmos#create-repositories) definition is same as above.
You can put different database entities into different packages.

### Setup configuration
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.
<!-- embedme src/samples/java/com/azure/cosmos/multidatasource/DatabaseConfiguration.java#L25-L76 -->
```java
@Configuration
@PropertySource("classpath:application.properties")
public class DatabaseConfiguration extends AbstractCosmosConfiguration {

@Bean
@ConfigurationProperties(prefix = "azure.cosmos.primary")
public CosmosProperties primaryDataSourceConfiguration() {
return new CosmosProperties();
}

@Bean
@ConfigurationProperties(prefix = "azure.cosmos.secondary")
public CosmosProperties secondaryDataSourceConfiguration() {
return new CosmosProperties();
}

@EnableReactiveCosmosRepositories(basePackages = "com.azure.cosmos.multidatasource.primarydatasource")
public class PrimaryDataSourceConfiguration {
@Autowired
@Qualifier("primaryDataSourceConfiguration")
CosmosProperties properties;
@Bean
public CosmosConfig cosmosConfig() {
CosmosConfig cosmosConfig = CosmosConfig.builder()
.cosmosClientBuilder(new CosmosClientBuilder()
.key(properties.getKey()).endpoint(properties.getUri()))
.database(properties.getDatabase())
.enableQueryMetrics(properties.isQueryMetricsEnabled())
.build();
return cosmosConfig;
}

}

@EnableReactiveCosmosRepositories(basePackages = "com.azure.cosmos.multidatasource.secondarydatasource", reactiveCosmosTemplateRef = "secondaryReactiveCosmosTemplate")
public class SecondaryDataSourceConfiguration {
@Autowired
@Qualifier("secondaryDataSourceConfiguration")
CosmosProperties properties;
@Bean
public ReactiveCosmosTemplate secondaryReactiveCosmosTemplate(MappingCosmosConverter mappingCosmosConverter) {
CosmosConfig cosmosConfig = CosmosConfig.builder()
.cosmosClientBuilder(new CosmosClientBuilder()
.key(properties.getKey()).endpoint(properties.getUri()))
.database(properties.getDatabase())
.enableQueryMetrics(properties.isQueryMetricsEnabled())
.build();

return new ReactiveCosmosTemplate(new CosmosFactory(cosmosConfig), mappingCosmosConverter, cosmosConfig.getDatabase());
}
}
}
```

### Create an Application class
<!-- embedme src/samples/java/com/azure/cosmos/multidatasource/MultiDatasourceApplication.java#L23-L61 -->

```java
@SpringBootApplication
public class MultiDatasourceApplication implements CommandLineRunner {

@Autowired
private UserRepository userRepository;

@Autowired
private BookRepository bookRepository;


private final User user = new User("1024", "[email protected]", "1k", "Mars");
private final Book book = new Book("9780792745488", "Zen and the Art of Motorcycle Maintenance", "Robert M. Pirsig");


public static void main(String[] args) {
SpringApplication.run(MultiDatasourceApplication.class, args);
}

@Override
public void run(String... args) {
final List<User> users = this.userRepository.findByEmailOrName(this.user.getEmail(), this.user.getName()).collectList().block();
users.forEach(System.out::println);
final Book book = this.bookRepository.findById("9780792745488").block();
System.out.println(book);
}

@PostConstruct
public void setup() {
this.userRepository.save(user).block();
this.bookRepository.save(book).block();

}

@PreDestroy
public void cleanup() {
this.userRepository.deleteAll().block();
this.bookRepository.deleteAll().block();
}
}
```

## Beta version package

Beta version built from `master` branch are available, you can refer to the [instruction](https://github.com/Azure/azure-sdk-for-java/blob/master/CONTRIBUTING.md#nightly-package-builds) to use beta version packages.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ public final class Constants {

public static final String COSMOS_MODULE_NAME = "cosmos";
public static final String COSMOS_MODULE_PREFIX = "cosmos";
public static final String COSMOS_MAPPING_CONTEXT = "cosmosMappingContext";

public static final String USER_AGENT_SUFFIX = "spring-data/";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@
package com.azure.spring.data.cosmos.repository.config;

import com.azure.spring.data.cosmos.Constants;
import com.azure.spring.data.cosmos.core.mapping.CosmosMappingContext;
import com.azure.spring.data.cosmos.repository.CosmosRepository;
import com.azure.spring.data.cosmos.repository.support.CosmosRepositoryFactoryBean;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.data.repository.config.AnnotationRepositoryConfigurationSource;
import org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport;
import org.springframework.data.repository.config.RepositoryConfigurationSource;
import org.springframework.data.repository.core.RepositoryMetadata;
Expand Down Expand Up @@ -57,19 +56,12 @@ protected Collection<Class<? extends Annotation>> getIdentifyingAnnotations() {
@Override
public void registerBeansForRoot(BeanDefinitionRegistry registry, RepositoryConfigurationSource config) {
super.registerBeansForRoot(registry, config);

if (!registry.containsBeanDefinition(Constants.COSMOS_MAPPING_CONTEXT)) {
final RootBeanDefinition definition = new RootBeanDefinition(CosmosMappingContext.class);
definition.setRole(AbstractBeanDefinition.ROLE_INFRASTRUCTURE);
definition.setSource(config.getSource());

registry.registerBeanDefinition(Constants.COSMOS_MAPPING_CONTEXT, definition);
}
}

@Override
public void postProcess(BeanDefinitionBuilder builder, RepositoryConfigurationSource source) {
super.postProcess(builder, source);
public void postProcess(BeanDefinitionBuilder builder, AnnotationRepositoryConfigurationSource source) {
final AnnotationAttributes attributes = source.getAttributes();
builder.addPropertyReference("cosmosOperations", attributes.getString("cosmosTemplateRef"));
}

// Overriding this to provide reactive repository support.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package com.azure.spring.data.cosmos.repository.config;

import com.azure.spring.data.cosmos.Constants;
import com.azure.spring.data.cosmos.core.CosmosTemplate;
import com.azure.spring.data.cosmos.repository.support.CosmosRepositoryFactoryBean;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Import;
Expand Down Expand Up @@ -92,5 +93,12 @@
* @return default value is false
*/
boolean considerNestedRepositories() default false;

/**
* Configures the name of the {@link CosmosTemplate} bean to be used with the repositories detected.
*
* @return {@literal cosmosTemplate} by default.
*/
String cosmosTemplateRef() default "cosmosTemplate";
}

Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package com.azure.spring.data.cosmos.repository.config;

import com.azure.spring.data.cosmos.Constants;
import com.azure.spring.data.cosmos.core.ReactiveCosmosTemplate;
import com.azure.spring.data.cosmos.repository.support.ReactiveCosmosRepositoryFactoryBean;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Import;
Expand Down Expand Up @@ -92,5 +93,12 @@
* @return default value is false
*/
boolean considerNestedRepositories() default false;

/**
* Configures the name of the {@link ReactiveCosmosTemplate} bean to be used with the repositories detected.
*
* @return {@literal reactiveCosmosTemplate} by default.
*/
String reactiveCosmosTemplateRef() default "reactiveCosmosTemplate";
}

Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@
package com.azure.spring.data.cosmos.repository.config;

import com.azure.spring.data.cosmos.Constants;
import com.azure.spring.data.cosmos.core.mapping.CosmosMappingContext;
import com.azure.spring.data.cosmos.repository.ReactiveCosmosRepository;
import com.azure.spring.data.cosmos.repository.support.ReactiveCosmosRepositoryFactoryBean;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.data.repository.config.AnnotationRepositoryConfigurationSource;
import org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport;
import org.springframework.data.repository.config.RepositoryConfigurationSource;
import org.springframework.data.repository.core.RepositoryMetadata;
Expand Down Expand Up @@ -57,19 +56,12 @@ protected Collection<Class<? extends Annotation>> getIdentifyingAnnotations() {
@Override
public void registerBeansForRoot(BeanDefinitionRegistry registry, RepositoryConfigurationSource config) {
super.registerBeansForRoot(registry, config);

if (!registry.containsBeanDefinition(Constants.COSMOS_MAPPING_CONTEXT)) {
final RootBeanDefinition definition = new RootBeanDefinition(CosmosMappingContext.class);
definition.setRole(AbstractBeanDefinition.ROLE_INFRASTRUCTURE);
definition.setSource(config.getSource());

registry.registerBeanDefinition(Constants.COSMOS_MAPPING_CONTEXT, definition);
}
}

@Override
public void postProcess(BeanDefinitionBuilder builder, RepositoryConfigurationSource source) {
super.postProcess(builder, source);
public void postProcess(BeanDefinitionBuilder builder, AnnotationRepositoryConfigurationSource source) {
final AnnotationAttributes attributes = source.getAttributes();
builder.addPropertyReference("reactiveCosmosOperations", attributes.getString("reactiveCosmosTemplateRef"));
}

// Overriding this to provide reactive repository support.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import com.azure.spring.data.cosmos.core.CosmosOperations;
import com.azure.spring.data.cosmos.repository.query.CosmosQueryMethod;
import com.azure.spring.data.cosmos.repository.query.PartTreeCosmosQuery;
import org.springframework.context.ApplicationContext;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.repository.core.EntityInformation;
import org.springframework.data.repository.core.NamedQueries;
Expand All @@ -27,18 +26,15 @@
*/
public class CosmosRepositoryFactory extends RepositoryFactorySupport {

private final ApplicationContext applicationContext;
private final CosmosOperations cosmosOperations;

/**
* Initialization
*
* @param cosmosOperations for cosmosDb operations
* @param applicationContext for the context
*/
public CosmosRepositoryFactory(CosmosOperations cosmosOperations, ApplicationContext applicationContext) {
public CosmosRepositoryFactory(CosmosOperations cosmosOperations) {
this.cosmosOperations = cosmosOperations;
this.applicationContext = applicationContext;
}

@Override
Expand All @@ -49,7 +45,7 @@ protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
@Override
protected Object getTargetRepository(RepositoryInformation information) {
final EntityInformation<?, Serializable> entityInformation = getEntityInformation(information.getDomainType());
return getTargetRepositoryViaReflection(information, entityInformation, this.applicationContext);
return getTargetRepositoryViaReflection(information, entityInformation, this.cosmosOperations);
}

@Override
Expand Down
Loading