16

How to expose an external resource (not managed through a repository) in the root listing of resources of Spring Data REST? I defined a controller following the pattern in Restbucks

Oliver Drotbohm
  • 80,157
  • 18
  • 225
  • 211
Stackee007
  • 3,196
  • 1
  • 26
  • 39

3 Answers3

23

This can be done by implementing ResourceProcessor<RepositoryLinksResource>.

Following code snippet adds "/others" to the root listing

@Controller
@ExposesResourceFor(Other.class)
@RequestMapping("/others")
public class CustomRootController implements
        ResourceProcessor<RepositoryLinksResource> {

    @ResponseBody
    @RequestMapping(method = RequestMethod.GET)
    public ResponseEntity<Resources<Resource<Other>>> listEntities(
            Pageable pageable) throws ResourceNotFoundException {
            //... do what needs to be done
    }

    @Override
    public RepositoryLinksResource process(RepositoryLinksResource resource) {
        resource.add(ControllerLinkBuilder.linkTo(CustomRootController.class).withRel("others"));

        return resource;
    }
}

should add

{
    "rel": "others",
    "href": "http://localhost:8080/api/others"
}

to your root listing links

Oliver Drotbohm
  • 80,157
  • 18
  • 225
  • 211
Stackee007
  • 3,196
  • 1
  • 26
  • 39
  • 2
    how can I do this for a non controller link? (specifically I want to add spring security logout) – xenoterracide Sep 17 '16 at 02:08
  • @xenoterracide maybe with a `@RequestMapping("/logout")` on the controller and then a `@RequestMapping(method = RequestMethod.POST) public logout(){ // do logout }` method. What do you mean non-controller link? – aycanadal Nov 18 '16 at 22:31
  • @aycanadal I'm fairly confident I figured that out at some point, but I have filter that I need to link to because, spring security – xenoterracide Nov 18 '16 at 22:36
  • In case of repository is `@RepositoryRestController` or `@BasePathAwareController` it also missed and HAL entry point and couldn't be discoreved, so linkTo created from root ("/"). Are there any solution for this? – Grigory Kislin Aug 10 '18 at 12:08
  • See also migration to Spring HATEOAS 1.0: https://stackoverflow.com/questions/56118868/migrating-resourceprocessor-to-hateoas-1-0-0-m1 – Grigory Kislin Feb 27 '20 at 13:16
2

I have been searching for an answer to the same issue, but the key is: I don't have a controller. My url points to something created in an auth filter. What worked for me is to create a RootController that doesn't have any methods, and use it for building links in the ResourceProcessor implementation.

@RestController
@RequestMapping("/")
public class RootController {}

Then the link is inserted using the empty controller.

@Component
public class AuthLinkProcessor implements ResourceProcessor<RepositoryLinksResource> {

    @Override
    public RepositoryLinksResource process(RepositoryLinksResource resource) {
        resource.add(
                linkTo(RootController.class)
                .slash("auth/login")
                .withRel("auth-login"));
        return resource;
    }
}
Ld00d
  • 41
  • 7
2

In 2022, API has changed. This reply might be relevant: Migrating ResourceProcessor to HATEOAS 1.0.0 M1.

Here's my piece of code with the new API:

@Component
class AuthLinkProcessor implements RepresentationModelProcessor<RepositoryLinksResource> {
    @Override
    public RepositoryLinksResource process(RepositoryLinksResource model) {
        model.add(
                linkTo(AuthenticationController.class)
                        .slash("/authenticate")
                        .withRel("authenticate"));
        return model;
    }
}
hsrv
  • 1,372
  • 10
  • 22