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

bluish picture bluish · Feb 6, 2015 · Viewed 9.7k times · Source

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?

Answer

Oliver Drotbohm picture Oliver Drotbohm · Feb 6, 2015

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.