Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Paginate sub-resources in Spring Data Rest 2.1

I use Spring Data Rest 2.1.1 Release with the default configuration. Considering the following resource:

GET /communities/MyCommunity

{
    "creationDate": "2014-07-16T06:22:37.153+0000",
    "name": "GroupeSEB",
    "_links": {
        "self": {
            "href": "http://localhost:8080/api/communities/GroupeSEB"
        },
        "posts": {
            "href": "http://localhost:8080/api/communities/GroupeSEB/posts"
        }
    }
}

When I get the "posts" sub-resource :

GET /communities/MyCommunity/posts

{
    "_embedded": {
        "posts": [
            {
                "creationDate": "2014-07-09T13:09:14.535+0000",
                "id": "53bd3efae4b012818368c549",
                "_links": {
                    "self": {
                        "href": "http://localhost:8080/api/posts/53bd3efae4b012818368c549"
                    } 
                }
            }
        ]
    }
}

No pagination is enabled. Since My parent resource can aggregate a large amount of posts (its sub-resource), how can I enable pagination for every sub-resources ?

like image 739
Maxime Avatar asked Jul 16 '14 08:07

Maxime


2 Answers

The answer is pretty simple: you can't. Here's the rationale:

Association resource represent the association between a a primary entity and one or many others. So to render these resources we lookup the primary entity and just access the property. This means, there's no repository usage and no place pagination can be applied as the entire mechanism is store agnostic. We operate on the entity instance The mechanism how associations are loaded is highly store specific.

So if you have object associations in your domain model already you're totally bound to the way the store treats associations. So even if you applied pagination, you would have to read all of the related objects in the first place to obtain their ids.

As a work around you could fall back to ids only and manually expose a resource right at that path which will use the ids and a dedicated query method on the repository of the associated entity.

like image 142
Oliver Drotbohm Avatar answered Oct 14 '22 13:10

Oliver Drotbohm


The answer given by Oliver is not entirely correct.

On EAGER nested entity (collection) the is no repository usage. But on LAZY nested entity (collection) there IS repository usage. @One2Many by default is LAZY. So the nested entity is not populated nor is it retrieved from repo when the parent entity is retrieved. The nested entity is only populated when it it accessed within the session. In Spring Data REST listing of parent entity never accesses the nested entity. When the nested LAZY entity is accessed via the nested entity access URL ie. /communities/GroupeSEB/posts is the nested Object accessed and as that nested object is not an object instance BUT LazyProxy of the object that will cause retrieval from repo. Ok, the nested object could be retrieved from Repo layer cache insead of the repo, but I think you can prohibit cache on the nested entity/object.

So if there was a way to pass/retrieve the paging info on LazyProxy implementation this could work.

P.S. I know they from experience as I made bi-directional navigation between @One2Many and @Many2One and to prevent N+1 on listing parents I set @ManyToOne(fetch = FetchType.LAZY) and then override the related findbyId() in repo interface with @NamedEntityGraph that forced the nested to EAGER when retrieved with @NamedEntityGraph. This does not apply directly to this problem but does demonstrate that within spring data rest the retrieval of nesetd entities is controllable.

like image 41
user3852017 Avatar answered Oct 14 '22 14:10

user3852017