Premise:
A web-service exposes its data via REST. Each record belongs to the user who created the record (row-level-security). Users may only retrieve own records.
@RepositoryRestResource(path = "talks")
public interface TalkRepository extends PagingAndSortingRepository<Talk, Long> {
@Override
@Query("select t from Talk t where t.owner.id= ?#{principal?.id}")
Page<Talk> findAll(Pageable pageable);
}
That repository is now available under a /talks endpoint.
Question:
Is there a way 1) to expose the same domain entity at multiple endpoints and 2) define different @Query annotations depending on the endpoint?
/talks/me/talks/me/** endpoints is exposed as public api to implementing clients.This question is partially related to https://jira.spring.io/browse/DATAREST-555, but only in so far that the additional path segment is currently not supported.
Rationale:
I like the idea of not having to put too much conditional logic into SPeL queries like is owner or has_some_role (some examples here). Further it would become easy to protect the /me/** endpoints by different strategies than the default API (e.g. only /me/** might be subject to OAuth2).
If you know better/more concise solutions I am happy to accept other answers.
Based on the suggestion of @OliverGierke, the official docs and various other SO answers (also almost exclusively by Oliver, mostly 1, 2 and 3) I have implemented a custom controller to serve the endpoint.
This also enables projections on the custom endpoint and uses Spring Data REST's HATEOS assembler to provide the HAL+JSON output. What I haven't worked on so far is how to reuse the profile and alps logic that SDR provides out of the box but gets lost within the custom controller.
@BasePathAwareController
public class MyTalksController {
private final TalkRepository repository;
private final PagedResourcesAssembler pagedResourcesAssembler;
@Autowired
public MyTalksController(TalkRepository repo, PagedResourcesAssembler assembler) {
repository = repo;
pagedResourcesAssembler = assembler;
}
@RequestMapping(method = RequestMethod.GET, value = "/me/talks")
@ResponseBody
public PagedResources<?> getTalks(Pageable pageable, PersistentEntityResourceAssembler entityAssembler) {
Page<Talk> talks = repository.meFindAll(pageable);
return pagedResourcesAssembler.toResource(talks, entityAssembler);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With