问题
I've a project with Spring Boot 1.5.7, Spring Data REST, Hibernate, Spring JPA, Swagger2.
I've two beans like these:
@Entity
public class TicketBundle extends AbstractEntity {
private static final long serialVersionUID = 404514926837058071L;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<Note> notes = new ArrayList<>();
.....
}
and
@Entity
public class Note extends AbstractEntity {
private static final long serialVersionUID = -5062313842902549565L;
@Lob
private String text;
...
}
I'm exposing my methods via Repository:
@Transactional
@RepositoryRestResource(excerptProjection = TicketBundleProjection.class)
@PreAuthorize("isAuthenticated()")
public interface TicketBundleRepository extends PagingAndSortingRepository<TicketBundle, Long> {
....
}
so in swagger I see the endpoint in which I'm interested that is needed to load the collection of notes from a specific ticket bundle:
Now, I want to override the default GET /api/v1/ticketBundles/{id}/notes
and replace that with my custom method I put in TicketBundleRepository
:
@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(@Param("id") long id, Pageable pageable);
It's very convenient create the query in this way because I need to use Pageable and return a Page. Unfortunately I've two problems at this point.
First problem
The method is mapped on the endpoint /api/v1/ticketBundles/search/ticketBundles/{id}/notes
instad of /api/v1/ticketBundles/ticketBundles/{id}/notes
Second problem When I call the method from swagger I receive an HTTP 404:
The request seems wrong. Seems the path variable is not understood:
curl -X GET --header 'Accept: application/json' 'http://localhost:8080/api/v1/ticketBundles/search/ticketBundles/{id}/notes?id=1'
This is the response from the server:
{
"timestamp": "2017-10-05T14:00:35.563+0000",
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/api/v1/ticketBundles/search/ticketBundles/%7Bid%7D/notes"
}
without any error on the server side.
Is there a way to override the endpoint GET/api/v1/ticketBundles/{id}/notes
exposing it through Repository
without using a custom controller (using that I would loose the facilities to manage the Pageable)?
Furthermore, what am I doing wrong to get a HTTP 404 in the call I shown above?
回答1:
I believe you are using incorrect annotations. You would need to annotate your class with @RestController
and use @PathVariable
on your method instead of @Param
. Here is a working sample, you may want to tailor it according to your needs.
@org.springframework.data.rest.webmvc.RepositoryRestController
@org.springframework.web.bind.annotation.RestController
public interface PersonRepository extends org.springframework.data.repository.PagingAndSortingRepository<Person, Long> {
@org.springframework.web.bind.annotation.GetMapping(path = "/people/{id}")
Person findById(@org.springframework.web.bind.annotation.PathVariable("id") Long id);
}
来源:https://stackoverflow.com/questions/46587861/customize-endpoints-with-spring-data-rest