Skip to content
This repository has been archived by the owner on Aug 29, 2024. It is now read-only.

Issue Spring Data Rest #225

Open
jannhendrik opened this issue Oct 11, 2018 · 5 comments
Open

Issue Spring Data Rest #225

jannhendrik opened this issue Oct 11, 2018 · 5 comments
Labels
Milestone

Comments

@jannhendrik
Copy link
Collaborator

Hi,
Using Spring Boot 2.0.5, Spring Data Rest 2.0.5 and Spring Data CosmosDB 2.0.5

When exposing paged resources and accessing them via RestAPI, paging does not work.

The first page is returned correctly, but onward from the second page an error is returned not a valid DocumentDbPageRequest, because continuation token is null.

If I understand the continuation token mechanism of cosmos db correctly the client of the API needs to receive the token (currently it is not returned) and send it with the request when querying again.

I wouldn't know a way to pass the continuation token through the Spring Data Rest generated endpoints, so this might be an incompatiblity.

Regards Jan

@sophiaso
Copy link
Member

Hi @jannhendrik, currently in spring-data-cosmosdb the continuation token is included in the query response and wrapped into the new returned page request. code here

If possible, could you provide a reproducible sample? If too huge, only the essential part might be enough, including dependencies, Repository and controller(if used).

@jannhendrik
Copy link
Collaborator Author

Sorry for answering so late. Please take a look at the following requests against the example project in this repo:

Request
curl -X GET \ 'http://localhost:8080/user?page=0&size=1' \ -H 'cache-control: no-cache'
Response:

{
    "_embedded": {
        "user": [
            {
                "email": "xxx-xx@xxx.com",
                "name": "myName_1",
                "count": 123,
                "address": {
                    "street": "zixing road",
                    "city": "shanghai"
                },
                "roleList": [
                    {
                        "name": "creator",
                        "cost": 234
                    },
                    {
                        "name": "contributor",
                        "cost": 666
                    }
                ],
                "_links": {
                    "self": {
                        "href": "http://localhost:8080/user/id_1"
                    },
                    "user": {
                        "href": "http://localhost:8080/user/id_1"
                    }
                }
            }
        ]
    },
    "_links": {
        "first": {
            "href": "http://localhost:8080/user?page=0&size=1"
        },
        "self": {
            "href": "http://localhost:8080/user{&sort}",
            "templated": true
        },
        "next": {
            "href": "http://localhost:8080/user?page=1&size=1"
        },
        "last": {
            "href": "http://localhost:8080/user?page=2&size=1"
        },
        "profile": {
            "href": "http://localhost:8080/profile/user"
        },
        "search": {
            "href": "http://localhost:8080/user/search"
        }
    },
    "page": {
        "size": 1,
        "totalElements": 3,
        "totalPages": 3,
        "number": 0
    }
}

Also the same 'user' is also returned for page two.

Request:
curl -X GET \ 'http://localhost:8080/user?page=1&size=1' \ -H 'cache-control: no-cache'
Resposne:
and

{
    "_embedded": {
        "user": [
            {
                "email": "xxx-xx@xxx.com",
                "name": "myName_1", **// should return myName_2**
                "count": 123,
                "address": {
                    "street": "zixing road",
                    "city": "shanghai"
                },
                "roleList": [
                    {
                        "name": "creator",
                        "cost": 234
                    },
                    {
                        "name": "contributor",
                        "cost": 666
                    }
                ],
                "_links": {
                    "self": {
                        "href": "http://localhost:8080/user/id_1"
                    },
                    "user": {
                        "href": "http://localhost:8080/user/id_1"
                    }
                }
            }
        ]
    },
    "_links": {
        "first": {
            "href": "http://localhost:8080/user?page=0&size=1"
        },
        "prev": {
            "href": "http://localhost:8080/user?page=0&size=1"
        },
        "self": {
            "href": "http://localhost:8080/user{&sort}",
            "templated": true
        },
        "next": {
            "href": "http://localhost:8080/user?page=2&size=1"
        },
        "last": {
            "href": "http://localhost:8080/user?page=2&size=1"
        },
        "profile": {
            "href": "http://localhost:8080/profile/user"
        },
        "search": {
            "href": "http://localhost:8080/user/search"
        }
    },
    "page": {
        "size": 1,
        "totalElements": 3,
        "totalPages": 3,
        "number": 1
    }
}

To my understanding the cosmos DB SQL API needs a continuation token to continue any earlier request.
So if page > 0 is requested and no continuation token is provided a bad request should be thrown.
Also as I stated earlier the continuation token needs to be returned (at least) in 'last' and 'next' page.

Regards Jan

@sophiaso
Copy link
Member

sophiaso commented Oct 17, 2018

Hi @jannhendrik, will check the issue if page > 0 is requested and no continuation token is provided a bad request should be thrown.

About how to use, you can refer one sample about how to use pagination for this spring-data-cosmosdb library.

The pagination query does return the continuation token in response json field requestContinuation:

    "pageable": {
        "sort": {
            "sorted": false,
            "unsorted": true
        },
        "requestContinuation": "-RID:g3c5AIwS92gCAAAAAAAAAA==#RT:1#TRC:1",
        "offset": 0,
        "pageNumber": 0,
        "pageSize": 1,
        "unpaged": false,
        "paged": true
    },
    "last": false,
    "totalPages": 3,
    "totalElements": 3,
    "size": 1,
    "number": 0,
    "sort": {
        "sorted": false,
        "unsorted": true
    },
    "numberOfElements": 1,
    "first": true

For above response, next page can be queried with:

http://localhost:8080/user?page=1&size=1&requestContinuation=-RID%3Ag3c5AIwS92gCAAAAAAAAAA%3D%3D%23RT%3A1%23TRC%3A1

The requestContinuation parameter has to be encoded as special characters exist in the continuation token.

You can write some REST API endpoint as:

    @GetMapping("/user")
    public Page<User> getUsers(DocumentDbPageRequest pageable) {
        return userRepository.findAll(pageable);
    }

The pageable should be a DocumentDbPageRequest in order to process the requestContinuation token.

@jannhendrik
Copy link
Collaborator Author

jannhendrik commented Oct 17, 2018 via email

@sophiaso
Copy link
Member

Hi @jannhendrik The @RestRepository is not supported.

@xscript xscript added this to the Backlog milestone Nov 30, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

4 participants