4

Considering Custom implementations for Spring Data repositories I am using the @RepositoryRestResource on repository to bring all the HATEOAS generated goodnes:

@RepositoryRestResource(collectionResourceRel = "people", path = "people")
public interface PersonRepository extends  PagingAndSortingRepository<PersonNode,Long>,
                                            PersonRepositoryCustom {


    List<PersonNode> findBySurname(@Param("0") String name);
}

Now following the mentioned docs I have created the PersonRepositoryCustom with additional, simple method for introductory purposes:

public interface PersonRepositoryCustom {

    public String printPerson(PersonNode personNode);
}

The implementation is:

public class PersonRepositoryImpl implements PersonRepositoryCustom{

    @Override
    public String printPerson(PersonNode personNode) {
        return "It Works!";
    }
}

I want the default SDR autogenerated endpoints to remain and just add the new custom methods/new implementations. How am I supposed to use this custom method with spring-data Rest/HATEOAS? With simple @RepositoryRestResource the controller endpoints are autogenerated. What if I want to provide some custom methods? I presume I would have to create controller manually but how should it look like in this exemplary case?

mCs
  • 2,591
  • 6
  • 39
  • 66

2 Answers2

1

First of all, such a method on repository like public String printPerson(PersonNode personNode) is a RPC style API and it is a known anti-pattern, so you should design your API in a REST-compliant-way (see e.g. How to design REST API for non-CRUD "commands" like activate and deactivate of a resource?)

The solution for your problem can looks as follows:

  1. Create a custom @RestController (as you supposed) with defined @RequestMappings for custom methods, which call relevant implementations.

  2. Create a new ResourceProcessor for your entity and override its process method, adding a new link to the resource that points your custom methods like /people/{id}/printPerson or whatever your mapping definition is.

Here an example from my project (Blog entity needs to list its Categories):

@Component
public static class BlogResourceProcessor implements ResourceProcessor<Resource<Blog>> {
    @Override
    public Resource<Blog> process(Resource<Blog> blogResource) {
        UriComponents uriComponents = ServletUriComponentsBuilder.fromCurrentContextPath()
                .path("/blog/{id}/categories").buildAndExpand(Long.toString(blogResource.getContent().getId()));
        blogResource.add(new Link(uriComponents.toUriString(), "categories"));
        return blogResource;
    }
}
Community
  • 1
  • 1
Adam Bogdan Boczek
  • 1,720
  • 6
  • 21
  • 34
-1

The custom method is added so you can use that in your code elsewhere where you would a PersonRepository. It doesn't magically map it to a REST operation, but the existing PagingAndSortingRepository mappings will remain.

Tommy B
  • 187
  • 2
  • 8