I want to create a Link to a resource within a Spring Data REST Repository. I know that we can use ControllerLinkBuilder.linkTo
method to create links to MVC controllers. As far is I understand Spring Data REST creates MVC controllers out of our Repository interfaces. But if I use
Instance createdInstance = instanceRepository.save(instance);
Link link = linkTo(InstanceRepository.class).slash(createdInstance.getId()).withSelfRel();
to create the link, I just get http://localhost:8080/2
(without the Repository path). Nothing changes if I specify the path explicitly with the @RepositoryRestResource
at the Repository.
Of course I could just create the link explicitly, but I don't want to repeat myself.
public interface InstanceRepository extends CrudRepository<Instance, Long> {
}
Any advice on what I could do to resolve this issue without having to violate DRY principles?
Spring Data REST is part of the umbrella Spring Data project and makes it easy to build hypermedia-driven REST web services on top of Spring Data repositories. Spring Data REST builds on top of Spring Data repositories, analyzes your application’s domain model and exposes hypermedia-driven HTTP resources for aggregates contained in the model.
At runtime, Spring Data REST automatically creates an implementation of this interface. Then it uses the @RepositoryRestResource annotation to direct Spring MVC to create RESTful endpoints at /people. @RepositoryRestResource is not required for a repository to be exported.
There is a people link located at http://localhost:8080/people. It has some options, such as ?page, ?size, and ?sort. Spring Data REST uses the HAL format for JSON output. It is flexible and offers a convenient way to supply links adjacent to the data that is served.
This repository is an interface that lets you perform various operations involving Person objects. It gets these operations by extending the PagingAndSortingRepository interface that is defined in Spring Data Commons.
Searching through the Spring Data REST source code I found the class RepositoryEntityLinks, which is used within the framework. It has a pretty nasty constructor, but (at least in my project) I am able to @Autowire
the class.
In short the following code does the trick. Nevertheless I would be pleased to hear another persons more educated opinion on this!
Link link = entityLinks.linkToSingleResource(InstanceRepository.class, 1L);
If anyone is confused on how to piece it all together, you need to inject RepsitoryEntityLinks
into your controller like so. Note no AutoWired
is needed since spring will automatically inject the values if theres just the 1 constructor.
entityLinks.linkToCollectionResource(TodoRepository.class)
is saying to spring - "give me the link to the TodoRepositories collection endpoint which would be something like localhost:8080/api/todos
"
@RestController
@RequestMapping(value="/api")
public class PriorityController {
private RepositoryEntityLinks entityLinks;
public PriorityController(RepositoryEntityLinks entityLinks) {
this.entityLinks = entityLinks;
}
@GetMapping(value = "/priorities", produces = MediaTypes.HAL_JSON_VALUE)
public ResponseEntity<Resources<Priority>> getPriorities() {
Link link = entityLinks.linkToCollectionResource(TodoRepository.class);
resources.add(link);
return ResponseEntity.ok(resources);
}
}
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