With Graph SDK v6.1 MS introduced the new PageIterator class to iterate over collection objects. We need this new feature for a lot of different collection types. Because of this, I would like to create a generic paging function, that can iterate over all different collections. But I was not able, to implement it satisfyingly. I see the following things, I would like to improve:
- We have to write the query configuration twice – once for the first query and a second time for the PageIterator
- Every Response Type has explicitly to be added in the PageIterator’s collectionPageFactory
Does someone have the same problem or/and have Ideas to improve our current solution?
Our code looks like this:
@Suppress("UNCHECKED_CAST")
fun getServicePrincipals(): List<ServicePrincipal> {
try {
val servicePrincipalCollectionResponse = graphServiceClient.servicePrincipals().get { requestConfiguration ->
requestConfiguration.queryParameters.select = arrayOf(SERVICE_PRINCIPALS_SELECT_PARAMETER)
requestConfiguration.queryParameters.top = azureConfig.pagingPageSize
}
val requestInformationMap: Map<String, Any> = mapOf(
"%24select" to arrayOf(SERVICE_PRINCIPALS_SELECT_PARAMETER),
"%24top" to azureConfig.pagingPageSize
)
return getResponseOfAllPages(servicePrincipalCollectionResponse, requestInformationMap) as List<ServicePrincipal>
} catch (e: ApiException) {
log.error("Error while getting servicePrincipals: ${e.message}")
return emptyList()
}
}
private fun getResponseOfAllPages(baseCollectionPaginationCountResponse: BaseCollectionPaginationCountResponse, requestInformationMap: Map<String, Any>): List<Entity> {
val entities = mutableListOf<Entity>()
val pageIterator = PageIterator.Builder<Entity, BaseCollectionPaginationCountResponse>()
.client(graphServiceClient)
.collectionPage(baseCollectionPaginationCountResponse)
.collectionPageFactory(
when (baseCollectionPaginationCountResponse) {
is ApplicationCollectionResponse -> ApplicationCollectionResponse::createFromDiscriminatorValue
is DirectoryObjectCollectionResponse -> DirectoryObjectCollectionResponse::createFromDiscriminatorValue
is AppRoleAssignmentCollectionResponse -> AppRoleAssignmentCollectionResponse::createFromDiscriminatorValue
is ServicePrincipalCollectionResponse -> ServicePrincipalCollectionResponse::createFromDiscriminatorValue
else -> throw IllegalArgumentException("No response of type ApplicationCollectionResponse, DirectoryObjectCollectionResponse, AppRoleAssignmentCollectionResponse, ServicePrincipalCollectionResponse found. Please implement handling any other type.")
}
)
.processPageItemCallback { entities.add(it) }
.requestConfigurator { requestInformation ->
requestInformationMap.forEach {
requestInformation.addQueryParameter(it.key, it.value)
}
requestInformation
}
.build()
pageIterator.iterate()
return entities
}