Search code examples
javaspringrestprojectionspring-data-rest

How do I apply a projection to a Spring Data REST query method resource?


I'm using Spring Data REST 2.1.4.RELEASE.

I created

  • an entity Booking,
  • its REST repository (extending CrudRepository) named BookingRepository
  • and a projection BookingDetails (annotated with @Projection(name="details", types = Booking.class)) for returning some of its linked entities exploded, such as Resource, Activity, Applicant etc.

The client gets all bookings with .../rest/bookings and the JSON response includes links for the linked entities. If it adds ?projection=details then the linked entities are exploded and returned. And this is great.

Now I add this custom method to the repository:

List<Booking> findByApplicant(@Param("applicant") Person applicant);

When the client invokes it with .../rest/bookings/search/findByApplicant?applicant=5, there seem to be no way to request the details projection. Following attempts are ignored:

  • adding &projection=details to the query string
  • making the method always return BookingDetails:

    List<BookingDetails> findByApplicant(@Param("applicant") Person applicant);
    

Summarizing, custom search methods (findBy*) never return a projection. Unless you annotate the repository with @RepositoryRestResource(excerptProjection = BookingDetails.class), but this leads to some problems, first of all the client has to always use the same projection. How can we allow the user to use projections also with findBy* methods?


Solution

  • I verfied this working with Spring Data REST 2.2.1, so please update it. Make sure your client actually sends the the requested parameters as you intend. While debugging, I found out that e.g. cURL drops query parameters if you do not explicitly quote the URI. So this:

    curl http://localhost:8080/orders/search/findByApplicant?applicant=5&projection=details
    

    will not send any of the query parameters. Once you quote the URI, it will.

    curl 'http://localhost:8080/orders/search/findByApplicant?applicant=5&projection=details'
    

    Sort of the same is in place for the increasingly popular HTTPie. With it the required syntax is:

    http :8080/orders/search/findByApplicant applicant==5 projection==details
    

    In case you can't get it to work that way, it would be cool to get a running example project to look at.