Add link to Spring Data REST Repository resource
Asked Answered
D

2

7

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?

Dump answered 20/8, 2015 at 9:10 Comment(0)
D
14

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);
Dump answered 20/8, 2015 at 15:33 Comment(3)
Nothing to add, except that the upcoming version 2.4.0 will mention that in the reference documentation explicitly (see DATAREST-623 for details).Eanes
I am unable to @Autowire RepositoryEntityLinks inside of my ResourceAssemblerSupport class. Are you @Autowiring in a @RestController?Wehrmacht
And for relation OneToMany, when i want to have all link for nested object ?Rieth
P
3

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);
        }
    }
Propose answered 23/9, 2017 at 5:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.