Closed lucprosa closed 4 years ago
@lucprosa Did you try the recommended way of pagination provided in the readme section of spring-data-cosmosdb: https://github.com/microsoft/spring-data-cosmosdb/blob/master/README.md Section: Supports Spring Data pageable and sort.
Also documented here: https://docs.microsoft.com/en-us/azure/java/spring-framework/how-to-guides-spring-data-cosmosdb#pagination-and-sorting
@kushagraThapar Yes, I saw that I was using a "Pageable" object to control de pagination and not the "CosmosPageRequest" that uses requestContinuation token and is recommended by documentation. Thanks for your response.
But I already changed my code here and it still give me a error when I try to pass a requestContinuation to get the next page of request.
Now I getting a "INVALID JSON" error: "Failed to query items; nested exception is CosmosClientException{error={\"message\":\"INVALID JSON in continuation token {\\\\"token\\\\":\\\\"+RID:~I9lLALNXyUM5EwAAAAAAAA== for Parallel~Context\"}, resourceAddress='null', statusCode=400, message=INVALID JSON in continuation token {\\"token\\":\\"+RID:~I9lLALNXyUM5EwAAAAAAAA== for Parallel~Context, causeInfo=null, responseHeaders={}, requestHeaders=null}",
I created a Python script to make the requests through my API. I get the requestPagination of current request to use in the next request to get the next page.
r = requests.post(urlAPI + '&page=' + str(page) + '&requestContinuation=' + str(previousRequestContinuation), data=body, headers=header)
@lucprosa can you please provide updated code snippet ? How are you getting the continuation token and using it for next pageable ? If you are getting it from response, you should not get invalid json .
Sure, follow my code below.
But I guess I found the gap here. It was the encoding of the parameter.
Controller:
@RestController
@RequestMapping(path = Array("/api"))
class DocumentController(@Autowired private val service: DocumentService) extends BaseController {
@PostMapping(path = Array("/documents/recent"), produces = Array("application/json"))
def findRecentDocuments(@RequestParam(required = false, defaultValue = "0") page: Int,
@RequestParam(required = false, defaultValue = "100") size: Int,
@RequestParam(required = false) requestContinuation: String,
@RequestBody params: DocumentParams,
@RequestHeader(name="apiKey") token: String
): Page[Document] = {
val pageable: PageParams = PageParams(page, size, requestContinuation)
service.findRecentDocuments(pageable, Option(params))
}
Service:
@Service
class DocumentService(@Autowired private val documentRepository: DocumentRepository, @Autowired private val template: CosmosTemplate) extends BaseService {
def findRecentDocuments(pageable: PageParams, params: Option[DocumentParams]): Page[Document] = {
val documentClass = classOf[Document]
val collectionName = template.getCollectionName(documentClass)
val criteria = QueryUtils.getCriteria(params, documentClass)
println("page: " + pageable.getPage)
println("size: " + pageable.getSize)
println("requestContinuation: "+ pageable.getRequestContinuation)
val pageRequest: CosmosPageRequest = new CosmosPageRequest(pageable.page, pageable.size, pageable.requestContinuation)
getCriteriaInfo(criteria)
documentRepository.findRecentDocuments(pageRequest, criteria, documentClass, collectionName)
}
Repository:
@Repository
class DocumentRepository(@Autowired private val template: CosmosTemplate){
def findRecentDocuments(pageRequest: CosmosPageRequest, criteria: Criteria, documentClass: Class[Document], collectionName: String): Page[Document] = {
val query = new DocumentQuery(criteria)
template.paginationQuery(query.`with`(pageRequest), documentClass, collectionName)
}
When I send a request I received a pageable information like this:
"pageable": {
"sort": {
"unsorted": true,
"sorted": false,
"empty": true
},
"offset": 0,
"requestContinuation": "{\"token\":\"-RID:~I9lLALNXyUO2GwAAAAAAAA==#RT:2#TRC:101#ISV:2#IEO:65551#QCF:1\",\"range\":\"{\\\"min\\\":\\\"\\\",\\\"max\\\":\\\"05C1DFFFFFFFFC\\\",\\\"isMinInclusive\\\":true,\\\"isMaxInclusive\\\":false}\"}",
"pageNumber": 0,
"pageSize": 100,
"paged": true,
"unpaged": false
},
"totalPages": 59,
"totalElements": 5839,
"last": false,
"sort": {
"unsorted": true,
"sorted": false,
"empty": true
},
"numberOfElements": 100,
"first": true,
"size": 100,
"number": 0,
"empty": false
Sure.
Controller:
@RestController
@RequestMapping(path = Array("/api"))
class DocumentController(@Autowired private val service: DocumentService) extends BaseController {
@PostMapping(path = Array("/documents/recent"), produces = Array("application/json"))
def findRecentDocuments(@RequestParam(required = false, defaultValue = "0") page: Int,
@RequestParam(required = false, defaultValue = "100") size: Int,
@RequestParam(required = false) requestContinuation: String,
@RequestBody params: DocumentParams,
@RequestHeader(name="apiKey") token: String
): Page[Document] = {
val pageable: PageParams = PageParams(page, size, requestContinuation)
service.findRecentDocuments(pageable, Option(params))
}
Service:
@Service
class DocumentService(@Autowired private val documentRepository: DocumentRepository, @Autowired private val template: CosmosTemplate) extends BaseService {
def findRecentDocuments(pageable: PageParams, params: Option[DocumentParams]): Page[Document] = {
val documentClass = classOf[Document]
val collectionName = template.getCollectionName(documentClass)
val criteria = QueryUtils.getCriteria(params, documentClass)
println("page: " + pageable.getPage)
println("size: " + pageable.getSize)
println("requestContinuation: "+ pageable.getRequestContinuation)
val pageRequest: CosmosPageRequest = new CosmosPageRequest(pageable.page, pageable.size, pageable.requestContinuation)
getCriteriaInfo(criteria)
documentRepository.findRecentDocuments(pageRequest, criteria, documentClass, collectionName)
}
Repository:
@Repository
class DocumentRepository(@Autowired private val template: CosmosTemplate){
def findRecentDocuments(pageRequest: CosmosPageRequest, criteria: Criteria, documentClass: Class[Document], collectionName: String): Page[Document] = {
val query = new DocumentQuery(criteria)
template.paginationQuery(query.`with`(pageRequest), documentClass, collectionName)
}
When I send a request I received a pageable information like this:
"pageable": {
"sort": {
"unsorted": true,
"sorted": false,
"empty": true
},
"offset": 0,
"requestContinuation": "{\"token\":\"-RID:~I9lLALNXyUO2GwAAAAAAAA==#RT:2#TRC:101#ISV:2#IEO:65551#QCF:1\",\"range\":\"{\\\"min\\\":\\\"\\\",\\\"max\\\":\\\"05C1DFFFFFFFFC\\\",\\\"isMinInclusive\\\":true,\\\"isMaxInclusive\\\":false}\"}",
"pageNumber": 0,
"pageSize": 100,
"paged": true,
"unpaged": false
},
"totalPages": 59,
"totalElements": 5839,
"last": false,
"sort": {
"unsorted": true,
"sorted": false,
"empty": true
},
"numberOfElements": 100,
"first": true,
"size": 100,
"number": 0,
"empty": false
I guess I found the problem here. It's all about encoding the parameter before send to request.
from requests.utils import quote
encodeToken = quote(str(requestContinuation))
I don't get the JSON error now.
I'll still make some tests with pagination here but I think this issue can be closed by now.
Thanks
@lucprosa Thanks for providing the code, it looks good now. Glad it got resolved, please feel free to close the issue.
Sure. Thanks @kushagraThapar
i am facing similar issue. can some one please help on this
"paginationToken": "{\"compositeToken\":\"{\\"token\\":\\"+RID:~XGtkAKZ5mcBlBwAAAAAAAA==#RT:2#TRC:6#RTD:03v6tHWhTzQwL/nVyeVsBMHX21Px/+9L5A==#ISV:2#IEO:65551#FPC:AWAHAAAAAAAAaQcAAAAAAAA=\\",\\"range\\":\\"{\\\\"min\\\\":\\\\"\\\\",\\\\"max\\\\":\\\\"FF\\\\",\\\\"isMinInclusive\\\\":true,\\\\"isMaxInclusive\\\\":false}\\"}\",\"orderByItems\":[{\"item\":1.5910333972E9,\"map\":{\"item\":1.5910333972E9}}],\"rid\":\"XGtkAKZ5mcBjBwAAAAAAAA==\",\"inclusive\":true}", "messages": [ { "id": "ec6613da-06cb-4bbb-be8b-66116a35c031", "clientId": "test", "to": "springdata@jun1.com",
CODE SNIPPET: String continuationToken=((CosmosPageRequest) ((CosmosPageImpl) pagedResponse).getPageable()).getRequestContinuation(); map.put(continuationToken, response); return map
@11shobhit - try encoding the continuationToken
-> like done in the above resolution comment: https://github.com/microsoft/spring-data-cosmosdb/issues/484#issuecomment-583622882
thanks @kushagraThapar it works
Hi, I'm using spring-data-cosmosdb 2.2.2 with azure-cosmos 3.6.0 and Scala.
I'm using CosmosTemplate to create custom DocumentQueries using sorting and pagination.
My problem is to navigate through the pages in my request using requestContinuation. Every request (POST) is returning a requestContinuation like that:
"requestContinuation": "{\"compositeToken\":\"{\\\"token\\\":null,\\\"range\\\":\\\"{\\\\\\\"min\\\\\\\":\\\\\\\"05C1DFFFFFFFFC\\\\\\\",\\\\\\\"max\\\\\\\":\\\\\\\"FF\\\\\\\",\\\\\\\"isMinInclusive\\\\\\\":true,\\\\\\\"isMaxInclusive\\\\\\\":false}\\\"}\",\"orderByItems\":[{\"item\":\"8b90e589-09d8-42e7-a3e2-d26cf2c38a63\",\"map\":{\"item\":\"8b90e589-09d8-42e7-a3e2-d26cf2c38a63\"}}],\"rid\":\"I9lLALNXyUNECgEAAAAACA==\",\"inclusive\":true}"
The first thing I saw is the inner "token" is always null.
I tried to copy the whole string and put it on my request as parameter but it didn't work:
POST https://baseurl/api/documents/recent?page=1&requestContinuation=...
The requestContinuation never changes and the documents returned in the page are always the same. I'm using Postman and Insomnia.
I don't find good examples to use requestContinuation. Am I missing something? Maybe encoding the token with base64?
I don't know if the problem is just to pass the requestContinuation or if there's something wrong in my code.
In resume I'm just using paginationQuery method to execute a documentQuery with some criterias and a "pageable" object.
My Controller:
My service:
My repo:
Thanks for any help.