5

i have created a custom rest controller and I can access the API and get the result from the resource, the problem is, it doesn't appear in the HAL Browser.. how to expose this custom method in the HAL Browser? Thank You...

@RepositoryRestController
public class RevisionController {

    protected static final Logger LOG = LoggerFactory
            .getLogger(RevisionController.class);

    private final DisciplineRepository repository;

    Function<Revision<Integer, Discipline>, Discipline> functionDiscipline = new Function<Revision<Integer, Discipline>, Discipline>() {
        @Override
        public Discipline apply(Revision<Integer, Discipline> input) {
            return (Discipline) input.getEntity();
        }
    };

    @Inject
    public RevisionController(DisciplineRepository repository) {
        this.repository = repository;
    }

    @RequestMapping(method = RequestMethod.GET, value = "/disciplines/search/{id}/revisions")
    public @ResponseBody ResponseEntity<?> getRevisions(
            @PathVariable("id") Integer id) {

        Revisions<Integer, Discipline> revisions = repository.findRevisions(id);

        List<Discipline> disciplines = Lists.transform(revisions.getContent(),
                functionDiscipline);

        Resources<Discipline> resources = new Resources<Discipline>(disciplines);

        resources.add(linkTo(
                methodOn(RevisionController.class).getRevisions(id))
                .withSelfRel());

        return ResponseEntity.ok(resources);
    }


}
Azli Cn
  • 105
  • 1
  • 5

1 Answers1

4

Register a bean that implements a ResourceProcessor<RepositoryLinksResource> and you can add links to your custom controller to the root resource, and the HAL Browser will see it.

public class RootResourceProcessor implements ResourceProcessor<RepositoryLinksResource> {

@Override
public RepositoryLinksResource process(RepositoryLinksResource resource) {
    resource.add(ControllerLinkBuilder.linkTo(ControllerLinkBuilder.methodOn(RevisionController.class).getRevisions(null)).withRel("revisions"));
    return resource;
    }
}
Barmar
  • 741,623
  • 53
  • 500
  • 612
adam p
  • 1,214
  • 9
  • 18
  • 1
    I'm trying that, and it's failing for me with `java.lang.IllegalArgumentException: 'uriTemplate' must not be null`. (Your code seemed to be missing a close-paren after `getRevisions()`. ) – Eric J Turley Dec 05 '16 at 23:12
  • Thanks Eric, I've amended the code. As for your issue - could you post a more complete stack trace? It is possible that you will be able to fix this by having your custom controller class implement the ResourceProcessor interface rather than a standalone class - couple of rumblings about this elsewhere (https://stackoverflow.com/questions/38548834/spring-hateoas-exception-in-creating-a-new-link). – adam p Dec 07 '16 at 11:21
  • Well, now I'm getting `java.util.NoSuchElementException: ArrayList:854 Collections:1042 ControllerLinkBuilderFactory:139 [spring-hateoas] ControllerLinkBuilder:172 RootResourceProcessor:22)` which has `resource.add(linkTo(methodOn(MeetupController.class, 2L, 3L, 2d, 2d, null, null).finalize(2L, 3L, 2d, 2d, null, null)).withRel("meetups"));` (Stack truncated to fit in comment) – Eric J Turley Dec 07 '16 at 23:38
  • Without being able to see your controller code this is tricky to debug further. I'm not sure why you are passing those parameters to your method twice. Can you not do this? `resource.add(linkTo(methodOn(MeetupController.class).finalize(2L, 3L, 2d, 2d, null, null)).withRel("meetups"));` – adam p Dec 11 '16 at 18:56
  • (I had passed params twice because of a problem I thought that was fixing). Yes - adjusting it again (and apparently fixing whatever that other problem was) makes the method exposed on the HAL browser. But, (1) at the top level instead of where I'd like, i.e /meetups/finalize, (2) the params are hard-coded to those above, rather than templated, and (3) I'd like it to be available only as a POST (non-GET) – Eric J Turley Dec 12 '16 at 15:48
  • You're adding a link to your json response, not defining what HTTP methods are exposed where. If you want your link to be added to the response body for a specific entity, you can change your `ResourceProcessor` to do so, i.e. `implements ResourceProcessor>`. From this, you will be able to specify the params based on each resource. If you want to add a link that is a URI template, construct this manually rather than using the ControllerLinkBuilder. You won't be able to specify that this link is POST only here. – adam p Dec 12 '16 at 16:23
  • @adamp I want to add a couple of methods to my resource User. So I would that my methods are displayed inside the automanager UserRepository inside "search". I tried a lot of changes but HAL shows my methods into a separate row. That is quite annoying. Do you think there is a way to do that? Thanks – drenda Jun 20 '17 at 18:42
  • @drenda are these repository find methods or custom queries you wish to expose, or methods from another class? If you want to try customizing the /{resource}/search endpoint take a look at the example here: https://stackoverflow.com/a/29609195/4632176 – adam p Jun 30 '17 at 15:28