spring-projects / spring-data-rest

Simplifies building hypermedia-driven REST web services on top of Spring Data repositories
https://spring.io/projects/spring-data-rest
Apache License 2.0
920 stars 563 forks source link

Use @PathVariable into a Repository [DATAREST-1154] #1521

Open spring-projects-issues opened 7 years ago

spring-projects-issues commented 7 years ago

Daniele Renda opened DATAREST-1154 and commented

I'm using Spring Boot, Spring HATEOAS, Spring Data REST, Hibernate.

All my beans have a Repository in order to expose methods via REST. I would like to use a @PathVariable in the Repository without create a specific controller.

This is what I would like to do:

@PreAuthorize("isAuthenticated()")
public interface TicketBundleRepository extends JpaRepository<TicketBundle, Long> {

    @Transactional(readOnly = true)
    @RestResource(rel = "ticketBundleNotes", path = "/ticketBundles/{id}/notes")
    @RequestMapping(method = RequestMethod.GET, path = "/ticketBundles/{id}/notes")
    @Query("SELECT n FROM TicketBundle tb JOIN tb.notes n WHERE tb.id=:id ORDER BY n.createdDate DESC, n.id DESC")
    public Page<Note> getNotes(@PathVariable("id") long id, Pageable pageable);

Unfortunately this doesn't work and when I try to call the endpoint I've a http 405 error. I guess the @PathVariable is not supported.

So I turned down to this solution that I don't like so much though:

@Transactional(readOnly = true)
    @Query("SELECT n FROM TicketBundle tb JOIN tb.notes n WHERE tb.id=:id ORDER BY n.createdDate DESC, n.id DESC")
    public Page<Note> getNotes(@Param("id") long id, Pageable pageable);

In short, instead to have a path variable I ask for an url parameter. This works fine but I'm not able to reach my goal to have an enpoint uri like htttp://localhost/api/ticketBundles/{id}/notes.

There is a question opened here: https://stackoverflow.com/questions/46892724/use-pathvariable-into-a-repository-managed-by-spring-data-rest.

I am asking if this could be a new function to add to SDR


Affects: 3.0 GA (Kay)

spring-projects-issues commented 7 years ago

Oliver Drotbohm commented

We currently have no plans to add support for this. Writing a controller to front that method invocation is trivial and supporting @RequestMapping on repository query methods creates more questions than it answers

spring-projects-issues commented 7 years ago

Daniele Renda commented

Thanks for your reply Oliver. Writing a controller is not a big deal but was absolutely fastester use the repository due to facilities (@Query and Pagination). Anyway I understand your point.

jamesdh commented 1 year ago

Ok, so we took this advice and created a controller for the same resource for which we already had a @RepositoryRestResource. But if we use the same @RequestMapping name, it breaks the repository. So we have to create another resource name for the same resource. 😞

odrotbohm commented 1 year ago

Can you elaborate on "breaks the repository"? It can only be one of the two: you either want to blend into the repository URI space, then of course the original handling is replaced, or you simply expose a separate resource.

jamesdh commented 1 year ago

or you simply expose a separate resource

Exactly, now we have multiple endpoints for the same resource since we still make use of the @RepositoryRestResource. Confusing to end users of our API, and not very RESTful.

odrotbohm commented 1 year ago

But: why? You don't have to do that. If you want to avoid the auto-exposed search resource, simply have @RestResource(exported = false) on the method or customize repository detection as described in the reference documentation. You could then advertise your custom resource by adding the link to the RepresentationModel instances returned. Registering a RepresentationModelProcessor should do the trick for that.

That said, I, of course, might be missing something that wasn't conveyed yet.