I have pretty the same question as it has been asked here (Exposing link on collection entity in spring data REST). But nothing from that topic helps me to add custom link to collection call.
@Component
public class EventListResourceProcessor implements ResourceProcessor<Resources<Event>> {
@Autowired
private RepositoryEntityLinks entityLinks;
@Override
public Resources<Event> process(Resources<Event> events) {
events.add(entityLinks.linkToCollectionResource(Event.class).withRel("events"));
return events;
}
}
process method is never called in this case.
I need to call http://localhost:8080/event and get the following JSON with my_custom_link under _links section:
{
"_embedded": {
"event": [
{
"id": "1",
"name": "Updated event"
}]
},
"_links": {
"self": {
"href": "http://localhost:8080/event"
},
"profile": {
"href": "http://localhost:8080/profile/event"
},
"my_custom_link": {
"href": "http://localhost:8080/custom/"
}
},
"page": {
"size": 20,
"totalElements": 4,
"totalPages": 1,
"number": 0
}
}
}
Could you please advise me?
Thanks in advance!
Because I faced the same issue and I hoped an answer here. The solution is to declare a bean
ResourceProcessor
implementing the right generic type which extendsResourceSupport
.In our case for a paginable resource, the right
ResourceSupport
isPagedResources<Resource<MyInterface>>
as the following sample :I was in a similar situation to your question: I had read through the question/answers you linked and found none of them could solve the problem. Here was the eventual answer to my problem:
This
process
method was called for each Resource in the relevant collection of Resources being returned. TheMyInterface
interface andMyClass
class should be replaced with whatever you end up needing, but it was required to be written that way to get this to work. Here are the steps I used to get theprocess
method called correctly and to determine theMyInterface
type.I created a
process
method that simply tookResourceSupport
as the parameter. I created a breakpoint in the code and inspected what underlying class was extendingResourceSupport
. In my case it wasPersistentEntityResource
. This explained why usingResource<MyClass>
orResources<MyClass>
were never causing theprocess
method to be called:PersistentEntityResource
extendsResource<Object>
.I updated the
process
method takePersistentEntityResource
as the parameter. This caused theprocess
method to be called for more than my intended changes. I once again used the breakpoint to inspect thePersistentEntityResource
object with the intent of discovering what class could be found in theResource<Object>
that it extended. I discovered it was aProxy
class, and could not be cast toMyClass
as I had desired.I followed the answer found here to find out more information about the
Proxy
class: https://stackoverflow.com/a/3344386/1417690. While debugging, I discovered the list of interfaces that helped define this class. One of them was of typeMyProjectionInterface
. I now knew that the reason I couldn't useResource<Portal>
was because it was actually aResource<MyProjectionInterface>
.I had three different
Projections
that I needed to handle. Instead of creating three separateResourcePorcoessors
I created theMyInterface
and had all three of myprojection
interfaces extend it. TheMyInterface
only contained aLong getId()
method which all of theprojections
already supported anyway.I updated my code to use
Resource<MyInterface>
and added thelinkForSingleResource
usingMyClass
(that all of theprojections
relate to) and thegetId()
method I had defined inMyInterface
. This successfully added the desired link to each of the resources being returned.Hopefully these steps help others discover how to determine what type to use as the parameter for the
process
method.