Skip to content

Commit

Permalink
Workaround framework's issue with next page functionality (Azure#15591)
Browse files Browse the repository at this point in the history
  • Loading branch information
azabbasi authored Sep 24, 2020
1 parent 298fb25 commit 915994f
Show file tree
Hide file tree
Showing 9 changed files with 295 additions and 43 deletions.
6 changes: 5 additions & 1 deletion sdk/digitaltwins/azure-digitaltwins-core/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
# Release History

## 1.0.0-beta.2 (Unreleased)
## 1.0.0-beta.2 (2020-09-24)

### Fixes and improvements

- Paging functionality for list operations has been fixed.
- `listModelOptions` is renamed to `modelsListOptions` for naming consistency.

## 1.0.0-beta.1 (2020-09-22)

Expand Down
2 changes: 1 addition & 1 deletion sdk/digitaltwins/azure-digitaltwins-core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

This library provides access to the Azure Digital Twins service for managing twins, models, relationships, etc.

[Source code][source] | Package (maven) (TODO: Add package information)
[Source code][source] | [Package](https://search.maven.org/artifact/com.azure/azure-digitaltwins-core)

## Getting started

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ public <T> PagedFlux<T> listRelationships(String digitalTwinId, Class<T> clazz)
public <T> PagedFlux<T> listRelationships(String digitalTwinId, String relationshipName, Class<T> clazz) {
return new PagedFlux<>(
() -> withContext(context -> listRelationshipsFirstPage(digitalTwinId, relationshipName, clazz, context)),
nextLink -> withContext(context -> listRelationshipsNextPage(nextLink, clazz, context)));
nextLink -> withContext(context -> listRelationshipsNextPage(this.protocolLayer.getHost() + nextLink, clazz, context)));
}

<T> Mono<PagedResponse<T>> listRelationshipsFirstPage(String digitalTwinId, String relationshipName, Class<T> clazz, Context context) {
Expand All @@ -485,7 +485,7 @@ <T> Mono<PagedResponse<T>> listRelationshipsFirstPage(String digitalTwinId, Stri
objectPagedResponse.getStatusCode(),
objectPagedResponse.getHeaders(),
list,
SerializationHelpers.serializeContinuationToken(objectPagedResponse.getContinuationToken()),
objectPagedResponse.getContinuationToken(),
((PagedResponseBase) objectPagedResponse).getDeserializedHeaders());
}
);
Expand All @@ -512,15 +512,15 @@ <T> Mono<PagedResponse<T>> listRelationshipsNextPage(String nextLink, Class<T> c
objectPagedResponse.getStatusCode(),
objectPagedResponse.getHeaders(),
stringList,
SerializationHelpers.serializeContinuationToken(objectPagedResponse.getContinuationToken()),
objectPagedResponse.getContinuationToken(),
((PagedResponseBase)objectPagedResponse).getDeserializedHeaders());
});
}

<T> PagedFlux<T> listRelationships(String digitalTwinId, String relationshipName, Class<T> clazz, Context context) {
return new PagedFlux<>(
() -> listRelationshipsFirstPage(digitalTwinId, relationshipName, clazz, context),
nextLink -> listRelationshipsNextPage(nextLink, clazz, context));
nextLink -> listRelationshipsNextPage(this.protocolLayer.getHost() + nextLink, clazz, context));
}

/**
Expand All @@ -533,13 +533,13 @@ <T> PagedFlux<T> listRelationships(String digitalTwinId, String relationshipName
public PagedFlux<IncomingRelationship> listIncomingRelationships(String digitalTwinId) {
return new PagedFlux<>(
() -> withContext(context -> listIncomingRelationshipsFirstPageAsync(digitalTwinId, context)),
nextLink -> withContext(context -> listIncomingRelationshipsNextSinglePageAsync(nextLink, context)));
nextLink -> withContext(context -> listIncomingRelationshipsNextSinglePageAsync(this.protocolLayer.getHost() + nextLink, context)));
}

PagedFlux<IncomingRelationship> listIncomingRelationships(String digitalTwinId, Context context) {
return new PagedFlux<>(
() -> listIncomingRelationshipsFirstPageAsync(digitalTwinId, context),
nextLink -> listIncomingRelationshipsNextSinglePageAsync(nextLink, context));
nextLink -> listIncomingRelationshipsNextSinglePageAsync(this.protocolLayer.getHost() + nextLink, context));
}

Mono<PagedResponse<IncomingRelationship>> listIncomingRelationshipsFirstPageAsync(String digitalTwinId, Context context){
Expand All @@ -562,7 +562,7 @@ Mono<PagedResponse<IncomingRelationship>> listIncomingRelationshipsNextSinglePag
pagedIncomingRelationshipResponse.getStatusCode(),
pagedIncomingRelationshipResponse.getHeaders(),
convertedList,
SerializationHelpers.serializeContinuationToken(pagedIncomingRelationshipResponse.getContinuationToken()),
pagedIncomingRelationshipResponse.getContinuationToken(),
((PagedResponseBase)pagedIncomingRelationshipResponse).getDeserializedHeaders());
};

Expand Down Expand Up @@ -656,38 +656,32 @@ Mono<Response<DigitalTwinsModelData>> getModelWithResponse(String modelId, Conte
*/
@ServiceMethod(returns = ReturnType.COLLECTION)
public PagedFlux<DigitalTwinsModelData> listModels() {
return listModels(new ListModelOptions());
return listModels(new ModelsListOptions());
}

/**
* List the models in this digital twins instance based on some options.
* @param listModelOptions The options to follow when listing the models.
* @param modelsListOptions The options to follow when listing the models.
* @return A {@link PagedFlux} containing the retrieved {@link DigitalTwinsModelData} instances.
*/
@ServiceMethod(returns = ReturnType.COLLECTION)
public PagedFlux<DigitalTwinsModelData> listModels(ListModelOptions listModelOptions) {
return new PagedFlux<>(
() -> withContext(context -> listModelsSinglePageAsync(listModelOptions, context)),
nextLink -> withContext(context -> listModelsNextSinglePageAsync(nextLink, context)));
}

PagedFlux<DigitalTwinsModelData> listModels(Context context){
public PagedFlux<DigitalTwinsModelData> listModels(ModelsListOptions modelsListOptions) {
return new PagedFlux<>(
() -> listModelsSinglePageAsync(new ListModelOptions(), context),
nextLink -> listModelsNextSinglePageAsync(nextLink, context));
() -> withContext(context -> listModelsSinglePageAsync(modelsListOptions, context)),
nextLink -> withContext(context -> listModelsNextSinglePageAsync(this.protocolLayer.getHost() + nextLink, context)));
}

PagedFlux<DigitalTwinsModelData> listModels(ListModelOptions listModelOptions, Context context){
PagedFlux<DigitalTwinsModelData> listModels(ModelsListOptions modelsListOptions, Context context){
return new PagedFlux<>(
() -> listModelsSinglePageAsync(listModelOptions, context),
nextLink -> listModelsNextSinglePageAsync(nextLink, context));
() -> listModelsSinglePageAsync(modelsListOptions, context),
nextLink -> listModelsNextSinglePageAsync(this.protocolLayer.getHost() + nextLink, context));
}

Mono<PagedResponse<DigitalTwinsModelData>> listModelsSinglePageAsync(ListModelOptions listModelOptions, Context context){
Mono<PagedResponse<DigitalTwinsModelData>> listModelsSinglePageAsync(ModelsListOptions modelsListOptions, Context context){
return protocolLayer.getDigitalTwinModels().listSinglePageAsync(
listModelOptions.getDependenciesFor(),
listModelOptions.getIncludeModelDefinition(),
new DigitalTwinModelsListOptions().setMaxItemCount(listModelOptions.getMaxItemCount()),
modelsListOptions.getDependenciesFor(),
modelsListOptions.getIncludeModelDefinition(),
new DigitalTwinModelsListOptions().setMaxItemCount(modelsListOptions.getMaxItemCount()),
context)
.map(
objectPagedResponse -> {
Expand Down Expand Up @@ -718,7 +712,7 @@ Mono<PagedResponse<DigitalTwinsModelData>> listModelsNextSinglePageAsync(String
objectPagedResponse.getStatusCode(),
objectPagedResponse.getHeaders(),
convertedList,
SerializationHelpers.serializeContinuationToken(objectPagedResponse.getContinuationToken()),
objectPagedResponse.getContinuationToken(),
((PagedResponseBase)objectPagedResponse).getDeserializedHeaders());
});
}
Expand Down Expand Up @@ -1054,14 +1048,14 @@ public PagedFlux<EventRoute> listEventRoutes(EventRoutesListOptions options)
{
return new PagedFlux<>(
() -> withContext(context -> listEventRoutesFirstPage(options, context)),
nextLink -> withContext(context -> listEventRoutesNextPage(nextLink, context)));
nextLink -> withContext(context -> listEventRoutesNextPage(this.protocolLayer.getHost() + nextLink, context)));
}

PagedFlux<EventRoute> listEventRoutes(EventRoutesListOptions options, Context context)
{
return new PagedFlux<>(
() -> listEventRoutesFirstPage(options, context),
nextLink -> listEventRoutesNextPage(nextLink, context));
nextLink -> listEventRoutesNextPage(this.protocolLayer.getHost() + nextLink, context));
}

Mono<PagedResponse<EventRoute>> listEventRoutesFirstPage(EventRoutesListOptions options, Context context) {
Expand Down Expand Up @@ -1089,7 +1083,7 @@ Mono<PagedResponse<EventRoute>> listEventRoutesNextPage(String nextLink, Context
pagedEventRouteResponse.getStatusCode(),
pagedEventRouteResponse.getHeaders(),
convertedList,
SerializationHelpers.serializeContinuationToken(pagedEventRouteResponse.getContinuationToken()),
pagedEventRouteResponse.getContinuationToken(),
((PagedResponseBase) pagedEventRouteResponse).getDeserializedHeaders());
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -393,14 +393,14 @@ public PagedIterable<DigitalTwinsModelData> listModels() {

/**
* List the models in this digital twins instance based on some options.
* @param listModelOptions The options to follow when listing the models.
* @param modelsListOptions The options to follow when listing the models.
* @param context Additional context that is passed through the Http pipeline during the service call.
* @return A {@link PagedIterable} containing the retrieved {@link DigitalTwinsModelData} instances.
*/
@ServiceMethod(returns = ReturnType.COLLECTION)
public PagedIterable<DigitalTwinsModelData> listModels(ListModelOptions listModelOptions, Context context) {
public PagedIterable<DigitalTwinsModelData> listModels(ModelsListOptions modelsListOptions, Context context) {
return new PagedIterable<>(
digitalTwinsAsyncClient.listModels(listModelOptions, context));
digitalTwinsAsyncClient.listModels(modelsListOptions, context));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* The optional parameters when listing models.
*/
@Fluent
public final class ListModelOptions {
public final class ModelsListOptions {

/*
* The maximum number of items to retrieve per request. The server may
Expand All @@ -29,9 +29,9 @@ public Integer getMaxItemCount() {
* Sets the maximum number of items to retrieve per request. The server may choose to return less than the
* requested max.
* @param maxItemCount the maxItemCount value to set.
* @return the ListModelOptions object itself.
* @return the ModelsListOptions object itself.
*/
public ListModelOptions setMaxItemCount(Integer maxItemCount) {
public ModelsListOptions setMaxItemCount(Integer maxItemCount) {
this.maxItemCount = maxItemCount;
return this;
}
Expand All @@ -51,9 +51,9 @@ public ListModelOptions setMaxItemCount(Integer maxItemCount) {
/**
* Sets whether to include the model definition in the result. If false, only the model metadata will be returned.
* @param includeModelDefinition the includeModelDefinition value to set.
* @return the ListModelOptions object itself.
* @return the ModelsListOptions object itself.
*/
public ListModelOptions setIncludeModelDefinition(Boolean includeModelDefinition) {
public ModelsListOptions setIncludeModelDefinition(Boolean includeModelDefinition) {
this.includeModelDefinition = includeModelDefinition;
return this;
}
Expand All @@ -72,9 +72,9 @@ public ListModelOptions setIncludeModelDefinition(Boolean includeModelDefinition
/**
* Sets the model Ids that will have their dependencies retrieved.
* @param dependenciesFor the dependenciesFor value to set.
* @return the ListModelOptions object itself.
* @return the ModelsListOptions object itself.
*/
public ListModelOptions setDependenciesFor(List<String> dependenciesFor) {
public ModelsListOptions setDependenciesFor(List<String> dependenciesFor) {
this.dependenciesFor = dependenciesFor;
return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,21 @@
import com.azure.core.util.logging.ClientLogger;
import com.azure.digitaltwins.core.helpers.UniqueIdHelper;
import com.azure.digitaltwins.core.models.DigitalTwinsModelData;
import com.azure.digitaltwins.core.models.ModelsListOptions;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import reactor.test.StepVerifier;

import java.net.HttpURLConnection;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;

import static com.azure.digitaltwins.core.TestHelper.DISPLAY_NAME_WITH_ARGUMENTS;
import static com.azure.digitaltwins.core.TestHelper.assertRestException;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertTrue;

/**
* Async client implementation of the model tests defined in {@link ModelsTestBase}
Expand Down Expand Up @@ -101,6 +104,43 @@ public void createModelThrowsIfModelAlreadyExists(HttpClient httpClient, Digital
.verifyErrorSatisfies(ex -> assertRestException(ex, HttpURLConnection.HTTP_CONFLICT));
}

@ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS)
@MethodSource("com.azure.digitaltwins.core.TestHelper#getTestParameters")
@Override
public void listModelsMultiplePages(HttpClient httpClient, DigitalTwinsServiceVersion serviceVersion) {
DigitalTwinsAsyncClient asyncClient = getAsyncClient(httpClient, serviceVersion);

// Create some models
List<DigitalTwinsModelData> createdModels = new ArrayList<>();
createModelsRunner(asyncClient, (modelsList) -> StepVerifier.create(asyncClient.createModels(modelsList))
.assertNext(createdModelsResponseList -> {
createdModelsResponseList.forEach(item -> createdModels.add(item));
logger.info("Created models successfully");
})
.verifyComplete());

createdModels.forEach(Assertions::assertNotNull);

AtomicInteger pageCount = new AtomicInteger();

// List models in multiple pages and verify more than one page was viewed.
StepVerifier.create(asyncClient.listModels(new ModelsListOptions().setMaxItemCount(2)).byPage())
.thenConsumeWhile(
page -> {
pageCount.getAndIncrement();
logger.info("content for this page " + pageCount);
for (DigitalTwinsModelData model : page.getValue()) {
logger.info(model.getId());
}
return true;
})
.verifyComplete();

int finalPageCount = pageCount.get();

assertTrue(finalPageCount > 1);
}

@ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS)
@MethodSource("com.azure.digitaltwins.core.TestHelper#getTestParameters")
@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
package com.azure.digitaltwins.core;

import com.azure.core.http.HttpClient;
import com.azure.core.util.Context;
import com.azure.core.util.logging.ClientLogger;
import com.azure.digitaltwins.core.helpers.UniqueIdHelper;
import com.azure.digitaltwins.core.models.DigitalTwinsModelData;
import com.azure.digitaltwins.core.models.ModelsListOptions;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

import java.net.HttpURLConnection;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;

import static com.azure.digitaltwins.core.TestHelper.DISPLAY_NAME_WITH_ARGUMENTS;
Expand Down Expand Up @@ -97,6 +100,40 @@ public void createModelThrowsIfModelAlreadyExists(HttpClient httpClient, Digital
HttpURLConnection.HTTP_CONFLICT);
}

@ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS)
@MethodSource("com.azure.digitaltwins.core.TestHelper#getTestParameters")
@Override
public void listModelsMultiplePages(HttpClient httpClient, DigitalTwinsServiceVersion serviceVersion) {
DigitalTwinsClient client = getClient(httpClient, serviceVersion);

final List<DigitalTwinsModelData> createdModels = new ArrayList<>();
createModelsRunner(client, (modelsList) -> {
Iterable<DigitalTwinsModelData> createdModelsResponseList = client.createModels(modelsList);
createdModelsResponseList.forEach((modelData) -> {
createdModels.add(modelData);
logger.info("Created models successfully");
});
});

createdModels.forEach(Assertions::assertNotNull);

AtomicInteger pageCount = new AtomicInteger();

// List models in multiple pages
client.listModels(new ModelsListOptions().setMaxItemCount(2), Context.NONE)
.iterableByPage()
.forEach(digitalTwinsModelDataPagedResponse -> {
pageCount.getAndIncrement();
logger.info("content for this page " + pageCount);
for (DigitalTwinsModelData data: digitalTwinsModelDataPagedResponse.getValue())
{
logger.info(data.getId());
}
});

assertTrue(pageCount.get() > 1);
}

@ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS)
@MethodSource("com.azure.digitaltwins.core.TestHelper#getTestParameters")
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@ public abstract class ModelsTestBase extends DigitalTwinsTestBase {

@Test
public abstract void getModelThrowsIfModelDoesNotExist(HttpClient httpClient, DigitalTwinsServiceVersion serviceVersion);

@Test
public abstract void createModelThrowsIfModelAlreadyExists(HttpClient httpClient, DigitalTwinsServiceVersion serviceVersion);

@Test
public abstract void listModelsMultiplePages(HttpClient httpClient, DigitalTwinsServiceVersion serviceVersion);

@Test
public abstract void getModelThrowsIfModelIdInvalid(HttpClient httpClient, DigitalTwinsServiceVersion serviceVersion);

Expand Down
Loading

0 comments on commit 915994f

Please sign in to comment.