Exposing link on collection entity in spring data REST
Asked Answered
D

2

7

Using spring data REST I have exposed a ProjectRepository that supports listing projects and performing CRUD operations on them. When I go to http://localhost:8080/projects/ I get the list of projects as I expect.

What I am trying to do is add a custom action to the _links section of the JSON response for the Project Collection.

For example, I'd like the call to http://localhost:8080/projects/ to return something like this:

{
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/projects/{?page,size,sort}",
      "templated" : true
    },
    "search" : {
      "href" : "http://localhost:8080/projects/search"
    },
    "customAction" : {
       "href" : "http://localhost:8080/projects/customAction"
    }
  },
  "page" : {
    "size" : 20,
    "totalElements" : 0,
    "totalPages" : 0,
    "number" : 0
  }
}

Where customAction is defined in some controller.

I've tried creating the following class:

public class ProjectCollectionResourceProcessor implements ResourceProcessor<Resource<Collection<Project>>> {

    @Override
    public Resource<Collection<Project>> process(Resource<Collection<Project>> listResource) {
        // code to add the links to customAction here
        return listResource;
    }

}

and adding adding the following Bean to my applications configuration:

@Bean
public ProjectCollectionResourceProcessor projectCollectionResourceProcessor() {
    return new ProjectCollectionResourceProcessor();
}

But process(...) doesn't ever seem to get called. What is the correct way to add links to Collections of resources?

Derbyshire answered 17/6, 2014 at 22:10 Comment(1)
See also, this question: https://mcmap.net/q/1622301/-exposing-link-on-collection-entity-using-spring-hateoasNork
O
4

The collection resources render an instance of Resources<Resource<Project>>, not Resource<Collection<Project>>. So if you change the generic typing in your ResourceProcessor implementation accordingly that should work as you expect it.

Obituary answered 18/6, 2014 at 14:21 Comment(6)
adding below code didn't help public class ProjectsResourceProcessor implements ResourceProcessor<Resources<Project>> { @Autowired private EntityLinks entityLinks; @Override public Resources<Project> process(Resources<Project> resources) { resources.add(entityLinks.linkFor(Project.class).slash("custom") .withRel("custom")); return resources; } } Using SDR-2.1.0.RELEASEGastroenterostomy
In order for me to get it to work I had to implement ResourceProcessor<PagedResources> and within the code determine if it was a Project resource. Thanks for the help.Derbyshire
@Derbyshire I'm looking for some resources (learning ones :-) to implement your solution. I have a paged resource as well.Expect
@Derbyshire I wonder how your search end point link would look if it offered pagination.Expect
@Derbyshire How did you actually manage to do the type checking? Do you have a generic way to share with otherS?Cyclothymia
This doesn't work, ResourceProcessor<Resources<User>> will not be invoked for my paged aggregate root of /usersReahard
U
4

I had the same issue. What worked for me was:

public class ProjectsResourceProcessor implements ResourceProcessor<PagedResources<Resource<Project>>> {

    private final @NonNull EntityLinks entityLinks;

    @Override
    public PagedResources<Resource<Project>> process(PagedResources<Resource<Project>> pagedResources) {

       ...

        return pagedResources;
    }
}
Uniaxial answered 6/11, 2014 at 15:51 Comment(3)
when no project exist, links do not appears :'(Kaseykasha
There is an explicit check in ResourcesProcessorWrapper::isValueTypeMatch to check for empty content and it prevents the resource processor from firing.Phares
yup facing same issue .. any hack to overcome thisPodium

© 2022 - 2024 — McMap. All rights reserved.