Search code examples
javaspringspring-data-restspring-hateoas

Trying to link to JPA Repository query methods with Spring HATEOS and get IllegalArgumentException: 'uriTemplate' must not be null


In my app I have a foreign key relation between Things and Stuff where a given Thing may contain hundreds of Stuffs and I'm using Spring Data JPA to expose the Thing and Stuff repository's.

I want to display all the Stuff associated with the users selected Thing, but because of the size of the return I want to page the Stuff result.

Searching showed that it is not possible to add paging functionality to the embedded stuff links from a Thing return, so the below link as returned from my Thing repository can never be paged:

"stuff": {
    "href": "http://localhost:8080/api/things/1/stuff"
}

So I have added a custom method to my Stuff repository to get all Stuff by thing Id, and that works fine when called directly.

I want to add a Link to the Thing Resource return pointing at the custom search method to get all the assocated Stuff, but when I use the ControllerLinkBuilder.linkTo() method it fails with

java.lang.IllegalArgumentException: 'uriTemplate' must not be null
at org.springframework.util.Assert.hasText(Assert.java:181) ~[spring-core-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at org.springframework.web.util.UriTemplate.<init>(UriTemplate.java:61) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE]

Stuff Repo:

public interface StuffRepo extends JpaRepository<Stuff, Long> {

    Page<Stuff> findByThingId(@Param("thingId") Long thingId, Pageable pageable);
}

Configuration:

@Bean
ThingProcessor getThingProcessor()
{
    return new ThingProcessor();
}

public static class ThingProcessor implements ResourceProcessor<Resource<Thing>>{
    @Override
    public Resource<Thing> process(Resource<Thing> resource) {
        ControllerLinkBuilder.linkTo(ControllerLinkBuilder.methodOn(StuffRepo.class).findByThingId(resource.getContent().id, null));
        return resource;
    }
}

Am I missing some annotation or configuration? I have tried annotating the Repo and the method with @RestResource and it makes no difference. Also is there a better way to get a paged result for the sub objects?


Solution

  • I got around this using the RepositoryEntityLinks class, that gives you a list of Link objects, and from there I find the one I need using link.getRel()